root/OpenSceneGraph/trunk/src/osgViewer/View.cpp @ 9909

Revision 9909, 75.5 kB (checked in by robert, 5 years ago)

Added View::removeEventHandler(..) method and added check into addEventHandler() to prevent handlers being added twice.

  • 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 <osgViewer/Renderer>
15#include <osgViewer/View>
16#include <osgViewer/GraphicsWindow>
17
18#include <osg/io_utils>
19
20#include <osg/TextureCubeMap>
21#include <osg/TextureRectangle>
22#include <osg/Texture1D>
23#include <osg/TexMat>
24
25#include <osgUtil/Optimizer>
26#include <osgUtil/IntersectionVisitor>
27
28using namespace osgViewer;
29
30class CollectedCoordinateSystemNodesVisitor : public osg::NodeVisitor
31{
32public:
33
34    CollectedCoordinateSystemNodesVisitor():
35        NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
36       
37    META_NodeVisitor("osgViewer","CollectedCoordinateSystemNodesVisitor")
38
39    virtual void apply(osg::Node& node)
40    {
41        traverse(node);
42    }
43
44    virtual void apply(osg::CoordinateSystemNode& node)
45    {
46        if (_pathToCoordinateSystemNode.empty())
47        {
48            osg::notify(osg::INFO)<<"Found CoordianteSystemNode node"<<std::endl;
49            osg::notify(osg::INFO)<<"     CoordinateSystem = "<<node.getCoordinateSystem()<<std::endl;
50            _pathToCoordinateSystemNode = getNodePath();
51        }
52        else
53        {
54            osg::notify(osg::INFO)<<"Found additional CoordianteSystemNode node, but ignoring"<<std::endl;
55            osg::notify(osg::INFO)<<"     CoordinateSystem = "<<node.getCoordinateSystem()<<std::endl;
56        }
57        traverse(node);
58    }
59   
60    osg::NodePath _pathToCoordinateSystemNode;
61};
62
63
64/** callback class to use to allow matrix manipulators to query the application for the local coordinate frame.*/
65class ViewerCoordinateFrameCallback : public osgGA::MatrixManipulator::CoordinateFrameCallback
66{
67public:
68
69    ViewerCoordinateFrameCallback(osgViewer::View* view):
70        _view(view) {}
71   
72    virtual osg::CoordinateFrame getCoordinateFrame(const osg::Vec3d& position) const
73    {
74        osg::notify(osg::INFO)<<"getCoordinateFrame("<<position<<")"<<std::endl;
75
76        osg::NodePath tmpPath = _view->getCoordinateSystemNodePath();
77       
78        if (!tmpPath.empty())
79        {       
80            osg::Matrixd coordinateFrame;
81
82            osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(tmpPath.back());
83            if (csn)
84            {
85                osg::Vec3 local_position = position*osg::computeWorldToLocal(tmpPath);
86               
87                // get the coordinate frame in world coords.
88                coordinateFrame = csn->computeLocalCoordinateFrame(local_position)* osg::computeLocalToWorld(tmpPath);
89
90                // keep the position of the coordinate frame to reapply after rescale.
91                osg::Vec3d pos = coordinateFrame.getTrans();
92
93                // compensate for any scaling, so that the coordinate frame is a unit size
94                osg::Vec3d x(1.0,0.0,0.0);
95                osg::Vec3d y(0.0,1.0,0.0);
96                osg::Vec3d z(0.0,0.0,1.0);
97                x = osg::Matrixd::transform3x3(x,coordinateFrame);
98                y = osg::Matrixd::transform3x3(y,coordinateFrame);
99                z = osg::Matrixd::transform3x3(z,coordinateFrame);
100                coordinateFrame.preMultScale(osg::Vec3d(1.0/x.length(),1.0/y.length(),1.0/z.length()));
101
102                // reapply the position.
103                coordinateFrame.setTrans(pos);
104
105                osg::notify(osg::INFO)<<"csn->computeLocalCoordinateFrame(position)* osg::computeLocalToWorld(tmpPath)"<<coordinateFrame<<std::endl;
106
107            }
108            else
109            {
110                osg::notify(osg::INFO)<<"osg::computeLocalToWorld(tmpPath)"<<std::endl;
111                coordinateFrame =  osg::computeLocalToWorld(tmpPath);
112            }
113            return coordinateFrame;
114        }
115        else
116        {
117            osg::notify(osg::INFO)<<"   no coordinate system found, using default orientation"<<std::endl;
118            return osg::Matrixd::translate(position);
119        }
120    }
121   
122protected:
123    virtual ~ViewerCoordinateFrameCallback() {}
124   
125    osg::observer_ptr<osgViewer::View> _view;
126};
127
128
129View::View():
130    _fusionDistanceMode(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE),
131    _fusionDistanceValue(1.0f)
132{
133    // osg::notify(osg::NOTICE)<<"Constructing osgViewer::View"<<std::endl;
134
135    _startTick = 0;
136
137    _frameStamp = new osg::FrameStamp;
138    _frameStamp->setFrameNumber(0);
139    _frameStamp->setReferenceTime(0);
140    _frameStamp->setSimulationTime(0);
141
142    _scene = new Scene;
143
144    // make sure View is safe to reference multi-threaded.
145    setThreadSafeRefUnref(true);
146   
147    // need to attach a Renderer to the master camera which has been default constructed
148    getCamera()->setRenderer(createRenderer(getCamera()));
149
150    setEventQueue(new osgGA::EventQueue);
151   
152    setStats(new osg::Stats("View"));
153}
154
155
156View::View(const osgViewer::View& view, const osg::CopyOp& copyop):
157    osg::View(view,copyop),
158    osgGA::GUIActionAdapter(),
159    _fusionDistanceMode(view._fusionDistanceMode),
160    _fusionDistanceValue(view._fusionDistanceValue)
161{
162    _scene = new Scene;
163
164    // need to attach a Renderer to the master camera which has been default constructed
165    getCamera()->setRenderer(createRenderer(getCamera()));
166
167    setEventQueue(new osgGA::EventQueue);
168
169    setStats(new osg::Stats("View"));
170}
171
172View::~View()
173{
174    osg::notify(osg::INFO)<<"Destructing osgViewer::View"<<std::endl;
175}
176
177void View::take(osg::View& rhs)
178{
179    osg::View::take(rhs);
180
181#if 1
182    osgViewer::View* rhs_osgViewer = dynamic_cast<osgViewer::View*>(&rhs);   
183    if (rhs_osgViewer)
184    {
185   
186        // copy across rhs
187        _startTick = rhs_osgViewer->_startTick;
188        _frameStamp = rhs_osgViewer->_frameStamp;
189
190        if (rhs_osgViewer->getSceneData())
191        {
192            _scene = rhs_osgViewer->_scene;
193        }
194       
195        if (rhs_osgViewer->_cameraManipulator.valid())
196        {
197            _cameraManipulator = rhs_osgViewer->_cameraManipulator;
198        }
199       
200        _eventHandlers.insert(_eventHandlers.end(), rhs_osgViewer->_eventHandlers.begin(), rhs_osgViewer->_eventHandlers.end());
201
202        _coordinateSystemNodePath = rhs_osgViewer->_coordinateSystemNodePath;
203
204        _displaySettings = rhs_osgViewer->_displaySettings;
205        _fusionDistanceMode = rhs_osgViewer->_fusionDistanceMode;
206        _fusionDistanceValue = rhs_osgViewer->_fusionDistanceValue;
207       
208       
209        // clear rhs
210        rhs_osgViewer->_frameStamp = 0;
211        rhs_osgViewer->_scene = 0;
212        rhs_osgViewer->_cameraManipulator = 0;
213        rhs_osgViewer->_eventHandlers.clear();
214       
215        rhs_osgViewer->_coordinateSystemNodePath.clear();
216       
217        rhs_osgViewer->_displaySettings = 0;
218    }
219#endif
220    computeActiveCoordinateSystemNodePath();
221    assignSceneDataToCameras();
222}
223
224osg::GraphicsOperation* View::createRenderer(osg::Camera* camera)
225{
226    Renderer* render = new Renderer(camera);
227    camera->setStats(new osg::Stats("Camera"));
228    return render;
229}
230
231
232void View::init()
233{
234    osg::notify(osg::INFO)<<"View::init()"<<std::endl;
235   
236    osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();
237    initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);
238   
239    if (_cameraManipulator.valid())
240    {
241        _cameraManipulator->init(*initEvent, *this);
242    }
243}
244
245void View::setStartTick(osg::Timer_t tick)
246{
247    _startTick = tick;
248}
249
250void View::setSceneData(osg::Node* node)
251{
252    if (node==_scene->getSceneData()) return;
253
254    osg::ref_ptr<Scene> scene = Scene::getScene(node);
255
256    if (scene)
257    {
258        osg::notify(osg::INFO)<<"View::setSceneData() Sharing scene "<<scene.get()<<std::endl;
259        _scene = scene;
260    }
261    else
262    {
263        if (_scene->referenceCount()!=1)
264        {
265            // we are not the only reference to the Scene so we cannot reuse it.
266            _scene = new Scene;
267            osg::notify(osg::INFO)<<"View::setSceneData() Allocating new scene"<<_scene.get()<<std::endl;
268        }
269        else
270        {
271            osg::notify(osg::INFO)<<"View::setSceneData() Reusing exisitng scene"<<_scene.get()<<std::endl;
272        }
273
274        _scene->setSceneData(node);
275    }
276
277    if (getSceneData())
278    {       
279        // now make sure the scene graph is set up with the correct DataVariance to protect the dynamic elements of
280        // the scene graph from being run in parallel.
281        osgUtil::Optimizer::StaticObjectDetectionVisitor sodv;
282        getSceneData()->accept(sodv);
283       
284        // make sure that existing scene graph objects are allocated with thread safe ref/unref
285        if (getViewerBase() &&
286            getViewerBase()->getThreadingModel()!=ViewerBase::SingleThreaded)
287        {
288            getSceneData()->setThreadSafeRefUnref(true);
289        }
290       
291        // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
292        getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
293    }
294   
295    computeActiveCoordinateSystemNodePath();
296
297    assignSceneDataToCameras();
298}
299
300void View::setDatabasePager(osgDB::DatabasePager* dp)
301{
302    _scene->setDatabasePager(dp);
303}
304
305osgDB::DatabasePager* View::getDatabasePager()
306{
307    return _scene->getDatabasePager();
308}
309
310const osgDB::DatabasePager* View::getDatabasePager() const
311{
312    return _scene->getDatabasePager();
313}
314
315
316void View::setImagePager(osgDB::ImagePager* dp)
317{
318    _scene->setImagePager(dp);
319}
320
321osgDB::ImagePager* View::getImagePager()
322{
323    return _scene->getImagePager();
324}
325
326const osgDB::ImagePager* View::getImagePager() const
327{
328    return _scene->getImagePager();
329}
330
331
332void View::setCameraManipulator(osgGA::MatrixManipulator* manipulator)
333{
334    _cameraManipulator = manipulator;
335   
336    if (_cameraManipulator.valid())
337    {
338        _cameraManipulator->setCoordinateFrameCallback(new ViewerCoordinateFrameCallback(this));
339
340        if (getSceneData()) _cameraManipulator->setNode(getSceneData());
341       
342        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();
343
344        _cameraManipulator->home(*dummyEvent, *this);
345    }
346}
347
348void View::home()
349{
350    if (_cameraManipulator.valid())
351    {
352        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();
353        _cameraManipulator->home(*dummyEvent, *this);
354    }
355}
356
357
358void View::addEventHandler(osgGA::GUIEventHandler* eventHandler)
359{
360    EventHandlers::iterator itr = std::find(_eventHandlers.begin(), _eventHandlers.end(), eventHandler);
361    if (itr == _eventHandlers.end())
362    {
363        _eventHandlers.push_back(eventHandler);
364    }
365}
366
367void View::removeEventHandler(osgGA::GUIEventHandler* eventHandler)
368{
369    EventHandlers::iterator itr = std::find(_eventHandlers.begin(), _eventHandlers.end(), eventHandler);
370    if (itr != _eventHandlers.end())
371    {
372        _eventHandlers.erase(itr);
373    }
374}
375
376void View::setCoordinateSystemNodePath(const osg::NodePath& nodePath)
377{
378    _coordinateSystemNodePath.clear();
379    std::copy(nodePath.begin(),
380              nodePath.end(),
381              std::back_inserter(_coordinateSystemNodePath));
382}
383
384osg::NodePath View::getCoordinateSystemNodePath() const
385{
386    osg::NodePath nodePath;
387    for(ObserverNodePath::const_iterator itr = _coordinateSystemNodePath.begin();
388        itr != _coordinateSystemNodePath.end();
389        ++itr)
390    {
391        nodePath.push_back(const_cast<osg::Node*>(itr->get()));
392    }
393    return nodePath;
394}
395
396void View::computeActiveCoordinateSystemNodePath()
397{
398    // now search for CoordinateSystemNode's for which we want to track.
399    osg::Node* subgraph = getSceneData();
400   
401    if (subgraph)
402    {
403   
404        CollectedCoordinateSystemNodesVisitor ccsnv;
405        subgraph->accept(ccsnv);
406
407        if (!ccsnv._pathToCoordinateSystemNode.empty())
408        {
409           setCoordinateSystemNodePath(ccsnv._pathToCoordinateSystemNode);
410           return;
411        }
412    } 
413
414    // otherwise no node path found so reset to empty.
415    setCoordinateSystemNodePath(osg::NodePath());
416}
417
418void View::setUpViewAcrossAllScreens()
419{
420    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
421    if (!wsi)
422    {
423        osg::notify(osg::NOTICE)<<"View::setUpViewAcrossAllScreens() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
424        return;
425    }
426   
427    osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance();
428   
429    double fovy, aspectRatio, zNear, zFar;       
430    _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
431
432    osg::GraphicsContext::ScreenIdentifier si;
433    si.readDISPLAY();
434   
435    // displayNum has not been set so reset it to 0.
436    if (si.displayNum<0) si.displayNum = 0;
437   
438    unsigned int numScreens = wsi->getNumScreens(si);
439    if (numScreens==1)
440    {
441        if (si.screenNum<0) si.screenNum = 0;
442   
443        unsigned int width, height;
444        wsi->getScreenResolution(si, width, height);
445
446        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
447        traits->hostName = si.hostName;
448        traits->displayNum = si.displayNum;
449        traits->screenNum = si.screenNum;
450        traits->x = 0;
451        traits->y = 0;
452        traits->width = width;
453        traits->height = height;
454        traits->alpha = ds->getMinimumNumAlphaBits();
455        traits->stencil = ds->getMinimumNumStencilBits();
456        traits->windowDecoration = false;
457        traits->doubleBuffer = true;
458        traits->sharedContext = 0;
459        traits->sampleBuffers = ds->getMultiSamples();
460        traits->samples = ds->getNumMultiSamples();
461        if (ds->getStereo())
462        {
463            switch(ds->getStereoMode())
464            {
465                case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break;
466                case(osg::DisplaySettings::VERTICAL_INTERLACE):
467                case(osg::DisplaySettings::CHECKERBOARD):
468                case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break;
469                default: break;
470            }
471        }
472       
473        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
474
475        _camera->setGraphicsContext(gc.get());
476       
477        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
478        if (gw)
479        {
480            osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<std::endl;
481            gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
482        }
483        else
484        {
485            osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
486        }
487
488        double newAspectRatio = double(traits->width) / double(traits->height);
489        double aspectRatioChange = newAspectRatio / aspectRatio;
490        if (aspectRatioChange != 1.0)
491        {
492            _camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
493        }
494
495        _camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
496
497        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
498
499        _camera->setDrawBuffer(buffer);
500        _camera->setReadBuffer(buffer);
501
502    }
503    else
504    {
505
506        double translate_x = 0.0;
507
508        for(unsigned int i=0; i<numScreens; ++i)
509        {
510            si.screenNum = i;
511
512            unsigned int width, height;
513            wsi->getScreenResolution(si, width, height);
514            translate_x += double(width) / (double(height) * aspectRatio);
515        }
516       
517        bool stereoSlitScreens = numScreens==2 &&
518                                 ds->getStereoMode()==osg::DisplaySettings::HORIZONTAL_SPLIT &&
519                                 ds->getStereo();
520   
521        for(unsigned int i=0; i<numScreens; ++i)
522        {
523            si.screenNum = i;
524       
525            unsigned int width, height;
526            wsi->getScreenResolution(si, width, height);
527
528            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
529            traits->hostName = si.hostName;
530            traits->displayNum = si.displayNum;
531            traits->screenNum = si.screenNum;
532            traits->screenNum = i;
533            traits->x = 0;
534            traits->y = 0;
535            traits->width = width;
536            traits->height = height;
537            traits->alpha = ds->getMinimumNumAlphaBits();
538            traits->stencil = ds->getMinimumNumStencilBits();
539            traits->windowDecoration = false;
540            traits->doubleBuffer = true;
541            traits->sharedContext = 0;
542            traits->sampleBuffers = ds->getMultiSamples();
543            traits->samples = ds->getNumMultiSamples();
544            if (ds->getStereo())
545            {
546                switch(ds->getStereoMode())
547                {
548                    case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break;
549                    case(osg::DisplaySettings::VERTICAL_INTERLACE):
550                    case(osg::DisplaySettings::CHECKERBOARD):
551                    case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break;
552                    default: break;
553                }
554            }
555
556            osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
557
558            osg::ref_ptr<osg::Camera> camera = new osg::Camera;
559            camera->setGraphicsContext(gc.get());
560
561            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
562            if (gw)
563            {
564                osg::notify(osg::INFO)<<"  GraphicsWindow has been created successfully."<<gw<<std::endl;
565
566                gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(traits->x, traits->y, traits->width, traits->height );
567            }
568            else
569            {
570                osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
571            }
572
573            camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
574
575            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
576            camera->setDrawBuffer(buffer);
577            camera->setReadBuffer(buffer);
578
579            if (stereoSlitScreens)
580            {
581                unsigned int leftCameraNum = (ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT) ? 0 : 1;
582               
583                osg::ref_ptr<osg::DisplaySettings> ds_local = new osg::DisplaySettings(*ds);
584                ds_local->setStereoMode(leftCameraNum==i ? osg::DisplaySettings::LEFT_EYE : osg::DisplaySettings::RIGHT_EYE);
585                camera->setDisplaySettings(ds_local.get());
586               
587                addSlave(camera.get(), osg::Matrixd(), osg::Matrixd() );
588            }
589            else
590            {
591                double newAspectRatio = double(traits->width) / double(traits->height);
592                double aspectRatioChange = newAspectRatio / aspectRatio;
593
594                addSlave(camera.get(), osg::Matrixd::translate( translate_x - aspectRatioChange, 0.0, 0.0) * osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0), osg::Matrixd() );
595                translate_x -= aspectRatioChange * 2.0;
596            }
597        }
598    }
599
600    assignSceneDataToCameras();
601}
602
603void View::setUpViewInWindow(int x, int y, int width, int height, unsigned int screenNum)
604{
605    osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance();
606
607    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
608
609    traits->readDISPLAY();
610    if (traits->displayNum<0) traits->displayNum = 0;
611   
612    traits->screenNum = screenNum;
613    traits->x = x;
614    traits->y = y;
615    traits->width = width;
616    traits->height = height;
617    traits->alpha = ds->getMinimumNumAlphaBits();
618    traits->stencil = ds->getMinimumNumStencilBits();
619    traits->windowDecoration = true;
620    traits->doubleBuffer = true;
621    traits->sharedContext = 0;
622    traits->sampleBuffers = ds->getMultiSamples();
623    traits->samples = ds->getNumMultiSamples();
624    if (ds->getStereo())
625    {
626        switch(ds->getStereoMode())
627        {
628            case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break;
629            case(osg::DisplaySettings::VERTICAL_INTERLACE):
630            case(osg::DisplaySettings::CHECKERBOARD):
631            case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break;
632            default: break;
633        }
634    }
635
636    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
637
638    _camera->setGraphicsContext(gc.get());
639
640    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
641    if (gw)
642    {
643        osg::notify(osg::INFO)<<"View::setUpViewOnSingleScreen - GraphicsWindow has been created successfully."<<std::endl;
644        gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(x, y, width, height );
645    }
646    else
647    {
648        osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
649    }
650
651    double fovy, aspectRatio, zNear, zFar;       
652    _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
653
654    double newAspectRatio = double(traits->width) / double(traits->height);
655    double aspectRatioChange = newAspectRatio / aspectRatio;
656    if (aspectRatioChange != 1.0)
657    {
658        _camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
659    }
660
661    _camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
662
663    GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
664
665    _camera->setDrawBuffer(buffer);
666    _camera->setReadBuffer(buffer);
667}
668
669void View::setUpViewOnSingleScreen(unsigned int screenNum)
670{
671    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
672    if (!wsi)
673    {
674        osg::notify(osg::NOTICE)<<"View::setUpViewOnSingleScreen() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
675        return;
676    }
677
678    osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance();
679
680    osg::GraphicsContext::ScreenIdentifier si;
681    si.readDISPLAY();
682   
683    // displayNum has not been set so reset it to 0.
684    if (si.displayNum<0) si.displayNum = 0;
685
686    si.screenNum = screenNum;
687
688    unsigned int width, height;
689    wsi->getScreenResolution(si, width, height);
690
691    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
692    traits->hostName = si.hostName;
693    traits->displayNum = si.displayNum;
694    traits->screenNum = si.screenNum;
695    traits->x = 0;
696    traits->y = 0;
697    traits->width = width;
698    traits->height = height;
699    traits->alpha = ds->getMinimumNumAlphaBits();
700    traits->stencil = ds->getMinimumNumStencilBits();
701    traits->windowDecoration = false;
702    traits->doubleBuffer = true;
703    traits->sharedContext = 0;
704    traits->sampleBuffers = ds->getMultiSamples();
705    traits->samples = ds->getNumMultiSamples();
706    if (ds->getStereo())
707    {
708        switch(ds->getStereoMode())
709        {
710            case(osg::DisplaySettings::QUAD_BUFFER): traits->quadBufferStereo = true; break;
711            case(osg::DisplaySettings::VERTICAL_INTERLACE):
712            case(osg::DisplaySettings::CHECKERBOARD):
713            case(osg::DisplaySettings::HORIZONTAL_INTERLACE): traits->stencil = 8; break;
714            default: break;
715        }
716    }
717
718    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
719
720    _camera->setGraphicsContext(gc.get());
721
722    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
723    if (gw)
724    {
725        osg::notify(osg::INFO)<<"View::setUpViewOnSingleScreen - GraphicsWindow has been created successfully."<<std::endl;
726        gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, width, height );
727    }
728    else
729    {
730        osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
731    }
732
733    double fovy, aspectRatio, zNear, zFar;       
734    _camera->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
735
736    double newAspectRatio = double(traits->width) / double(traits->height);
737    double aspectRatioChange = newAspectRatio / aspectRatio;
738    if (aspectRatioChange != 1.0)
739    {
740        _camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
741    }
742
743    _camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
744
745    GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
746
747    _camera->setDrawBuffer(buffer);
748    _camera->setReadBuffer(buffer);
749}
750
751static osg::Geometry* create3DSphericalDisplayDistortionMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, double sphere_radius, double collar_radius,osg::Image* intensityMap, const osg::Matrix& projectorMatrix)
752{
753    osg::Vec3d center(0.0,0.0,0.0);
754    osg::Vec3d eye(0.0,0.0,0.0);
755   
756    double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius);
757   
758    bool centerProjection = false;
759
760    osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance);
761   
762    osg::notify(osg::INFO)<<"create3DSphericalDisplayDistortionMesh : Projector position = "<<projector<<std::endl;
763    osg::notify(osg::INFO)<<"create3DSphericalDisplayDistortionMesh : distance = "<<distance<<std::endl;
764
765
766    // create the quad to visualize.
767    osg::Geometry* geometry = new osg::Geometry();
768
769    geometry->setSupportsDisplayList(false);
770
771    osg::Vec3 xAxis(widthVector);
772    float width = widthVector.length();
773    xAxis /= width;
774
775    osg::Vec3 yAxis(heightVector);
776    float height = heightVector.length();
777    yAxis /= height;
778   
779    int noSteps = 50;
780
781    osg::Vec3Array* vertices = new osg::Vec3Array;
782    osg::Vec3Array* texcoords0 = new osg::Vec3Array;
783    osg::Vec2Array* texcoords1 = intensityMap==0 ? new osg::Vec2Array : 0;
784    osg::Vec4Array* colors = new osg::Vec4Array;
785
786    osg::Vec3 bottom = origin;
787    osg::Vec3 dx = xAxis*(width/((float)(noSteps-1)));
788    osg::Vec3 dy = yAxis*(height/((float)(noSteps-1)));
789   
790    osg::Vec3d screenCenter = origin + widthVector*0.5f + heightVector*0.5f;
791    float screenRadius = heightVector.length() * 0.5f;
792
793    osg::Vec3 cursor = bottom;
794    int i,j;
795
796    if (centerProjection)
797    {
798        for(i=0;i<noSteps;++i)
799        {
800            osg::Vec3 cursor = bottom+dy*(float)i;
801            for(j=0;j<noSteps;++j)
802            {
803                osg::Vec2 delta(cursor.x() - screenCenter.x(), cursor.y() - screenCenter.y());
804                double theta = atan2(-delta.y(), delta.x());
805                double phi = osg::PI_2 * delta.length() / screenRadius;
806                if (phi > osg::PI_2) phi = osg::PI_2;
807
808                phi *= 2.0;
809               
810                if (theta<0.0) theta += 2.0*osg::PI;
811
812                // osg::notify(osg::NOTICE)<<"theta = "<<theta<< "phi="<<phi<<std::endl;
813
814                osg::Vec3 texcoord(sin(phi) * cos(theta),
815                                   sin(phi) * sin(theta),
816                                   cos(phi));
817
818                vertices->push_back(cursor);
819                texcoords0->push_back(texcoord * projectorMatrix);
820
821                osg::Vec2 texcoord1(theta/(2.0*osg::PI), 1.0f - phi/osg::PI_2);
822                if (intensityMap)
823                {           
824                    colors->push_back(intensityMap->getColor(texcoord1));
825                }
826                else
827                {
828                    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
829                    if (texcoords1) texcoords1->push_back( texcoord1 );
830                }
831
832                cursor += dx;
833            }
834            // osg::notify(osg::NOTICE)<<std::endl;
835        }
836    }
837    else
838    {
839        for(i=0;i<noSteps;++i)
840        {
841            osg::Vec3 cursor = bottom+dy*(float)i;
842            for(j=0;j<noSteps;++j)
843            {
844                osg::Vec2 delta(cursor.x() - screenCenter.x(), cursor.y() - screenCenter.y());
845                double theta = atan2(-delta.y(), delta.x());
846                double phi = osg::PI_2 * delta.length() / screenRadius;
847                if (phi > osg::PI_2) phi = osg::PI_2;
848                if (theta<0.0) theta += 2.0*osg::PI;
849
850                // osg::notify(osg::NOTICE)<<"theta = "<<theta<< "phi="<<phi<<std::endl;
851               
852                double f = distance * sin(phi);
853                double e = distance * cos(phi) + sqrt( sphere_radius*sphere_radius - f*f);
854                double l = e * cos(phi);
855                double h = e * sin(phi);
856                double z = l - distance;
857               
858                osg::Vec3 texcoord(h * cos(theta) / sphere_radius,
859                                   h * sin(theta) / sphere_radius,
860                                   z / sphere_radius);
861
862                vertices->push_back(cursor);
863                texcoords0->push_back(texcoord * projectorMatrix);
864
865                osg::Vec2 texcoord1(theta/(2.0*osg::PI), 1.0f - phi/osg::PI_2);
866                if (intensityMap)
867                {           
868                    colors->push_back(intensityMap->getColor(texcoord1));
869                }
870                else
871                {
872                    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
873                    if (texcoords1) texcoords1->push_back( texcoord1 );
874                }
875
876                cursor += dx;
877            }
878            // osg::notify(osg::NOTICE)<<std::endl;
879        }
880    }
881   
882    // pass the created vertex array to the points geometry object.
883    geometry->setVertexArray(vertices);
884
885    geometry->setColorArray(colors);
886    geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
887
888    geometry->setTexCoordArray(0,texcoords0);
889    if (texcoords1) geometry->setTexCoordArray(1,texcoords1);
890
891    for(i=0;i<noSteps-1;++i)
892    {
893        osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP);
894        for(j=0;j<noSteps;++j)
895        {
896            elements->push_back(j+(i+1)*noSteps);
897            elements->push_back(j+(i)*noSteps);
898        }
899        geometry->addPrimitiveSet(elements);
900    }
901   
902    return geometry;
903}
904
905void View::setUpViewFor3DSphericalDisplay(double radius, double collar, unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix)
906{
907    osg::notify(osg::INFO)<<"View::setUpViewFor3DSphericalDisplay(rad="<<radius<<", cllr="<<collar<<", sn="<<screenNum<<", im="<<intensityMap<<")"<<std::endl;
908    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
909    if (!wsi)
910    {
911        osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
912        return;
913    }
914
915    osg::GraphicsContext::ScreenIdentifier si;
916    si.readDISPLAY();
917   
918    // displayNum has not been set so reset it to 0.
919    if (si.displayNum<0) si.displayNum = 0;
920
921    si.screenNum = screenNum;
922
923    unsigned int width, height;
924    wsi->getScreenResolution(si, width, height);
925
926
927    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
928    traits->hostName = si.hostName;
929    traits->displayNum = si.displayNum;
930    traits->screenNum = si.screenNum;
931    traits->x = 0;
932    traits->y = 0;
933    traits->width = width;
934    traits->height = height;
935    traits->windowDecoration = false;
936    traits->doubleBuffer = true;
937    traits->sharedContext = 0;
938   
939
940    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
941    if (!gc)
942    {
943        osg::notify(osg::NOTICE)<<"GraphicsWindow has not been created successfully."<<std::endl;
944        return;
945    }
946   
947    bool applyIntensityMapAsColours = true;
948
949    int tex_width = 512;
950    int tex_height = 512;
951
952    int camera_width = tex_width;
953    int camera_height = tex_height;
954
955    osg::TextureCubeMap* texture = new osg::TextureCubeMap;
956
957    texture->setTextureSize(tex_width, tex_height);
958    texture->setInternalFormat(GL_RGB);
959    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
960    texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
961    texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
962    texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
963    texture->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE);
964   
965#if 0   
966    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW;
967    GLenum buffer = GL_FRONT;
968#else
969    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
970    GLenum buffer = GL_FRONT;
971#endif
972
973    // front face
974    {
975        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
976        camera->setName("Front face camera");
977        camera->setGraphicsContext(gc.get());
978        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
979        camera->setDrawBuffer(buffer);
980        camera->setReadBuffer(buffer);
981        camera->setAllowEventFocus(false);
982        // tell the camera to use OpenGL frame buffer object where supported.
983        camera->setRenderTargetImplementation(renderTargetImplementation);
984
985        // attach the texture and use it as the color buffer.
986        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Y);
987
988        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
989    }
990
991   
992    // top face
993    {
994        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
995        camera->setName("Top face camera");
996        camera->setGraphicsContext(gc.get());
997        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
998        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
999        camera->setDrawBuffer(buffer);
1000        camera->setReadBuffer(buffer);
1001        camera->setAllowEventFocus(false);
1002
1003        // tell the camera to use OpenGL frame buffer object where supported.
1004        camera->setRenderTargetImplementation(renderTargetImplementation);
1005
1006        // attach the texture and use it as the color buffer.
1007        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Z);
1008
1009        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(-90.0f), 1.0,0.0,0.0));
1010    }
1011
1012    // left face
1013    {
1014        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1015        camera->setName("Left face camera");
1016        camera->setGraphicsContext(gc.get());
1017        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
1018        camera->setDrawBuffer(buffer);
1019        camera->setReadBuffer(buffer);
1020        camera->setAllowEventFocus(false);
1021
1022        // tell the camera to use OpenGL frame buffer object where supported.
1023        camera->setRenderTargetImplementation(renderTargetImplementation);
1024
1025        // attach the texture and use it as the color buffer.
1026        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_X);
1027
1028        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0,1.0,0.0) * osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0,0.0,1.0));
1029    }
1030
1031    // right face
1032    {
1033        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1034        camera->setName("Right face camera");
1035        camera->setGraphicsContext(gc.get());
1036        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
1037        camera->setDrawBuffer(buffer);
1038        camera->setReadBuffer(buffer);
1039        camera->setAllowEventFocus(false);
1040
1041        // tell the camera to use OpenGL frame buffer object where supported.
1042        camera->setRenderTargetImplementation(renderTargetImplementation);
1043
1044        // attach the texture and use it as the color buffer.
1045        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_X);
1046
1047        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0,1.0,0.0 ) * osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0,0.0,1.0));
1048    }
1049
1050    // bottom face
1051    {
1052        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1053        camera->setGraphicsContext(gc.get());
1054        camera->setName("Bottom face camera");
1055        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
1056        camera->setDrawBuffer(buffer);
1057        camera->setReadBuffer(buffer);
1058        camera->setAllowEventFocus(false);
1059
1060        // tell the camera to use OpenGL frame buffer object where supported.
1061        camera->setRenderTargetImplementation(renderTargetImplementation);
1062
1063        // attach the texture and use it as the color buffer.
1064        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_Z);
1065
1066        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(90.0f), 1.0,0.0,0.0) * osg::Matrixd::rotate(osg::inDegrees(180.0f), 0.0,0.0,1.0));
1067    }
1068
1069    // back face
1070    {
1071        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1072        camera->setName("Back face camera");
1073        camera->setGraphicsContext(gc.get());
1074        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
1075        camera->setDrawBuffer(buffer);
1076        camera->setReadBuffer(buffer);
1077        camera->setAllowEventFocus(false);
1078
1079        // tell the camera to use OpenGL frame buffer object where supported.
1080        camera->setRenderTargetImplementation(renderTargetImplementation);
1081
1082        // attach the texture and use it as the color buffer.
1083        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_Y);
1084
1085        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(180.0f), 1.0,0.0,0.0));
1086    }
1087   
1088    getCamera()->setProjectionMatrixAsPerspective(90.0f, 1.0, 1, 1000.0);
1089
1090    // distortion correction set up.
1091    {
1092        osg::Geode* geode = new osg::Geode();
1093        geode->addDrawable(create3DSphericalDisplayDistortionMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), radius, collar, applyIntensityMapAsColours ? intensityMap : 0, projectorMatrix));
1094
1095        // new we need to add the texture to the mesh, we do so by creating a
1096        // StateSet to contain the Texture StateAttribute.
1097        osg::StateSet* stateset = geode->getOrCreateStateSet();
1098        stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
1099        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
1100
1101        if (!applyIntensityMapAsColours && intensityMap)
1102        {
1103            stateset->setTextureAttributeAndModes(1, new osg::Texture2D(intensityMap), osg::StateAttribute::ON);
1104        }
1105
1106        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1107        camera->setGraphicsContext(gc.get());
1108        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
1109        camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
1110        camera->setViewport(new osg::Viewport(0, 0, width, height));
1111        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
1112        camera->setDrawBuffer(buffer);
1113        camera->setReadBuffer(buffer);
1114        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
1115        camera->setAllowEventFocus(false);
1116        camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
1117        //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
1118       
1119        camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
1120        camera->setViewMatrix(osg::Matrix::identity());
1121
1122        // add subgraph to render
1123        camera->addChild(geode);
1124       
1125        camera->setName("DistortionCorrectionCamera");
1126
1127        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
1128    }
1129   
1130    getCamera()->setNearFarRatio(0.0001f);
1131   
1132    if (getLightingMode()==osg::View::HEADLIGHT)
1133    {
1134        // set a local light source for headlight to ensure that lighting is consistent across sides of cube.
1135        getLight()->setPosition(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
1136    }
1137}
1138
1139static osg::Geometry* createParoramicSphericalDisplayDistortionMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, double sphere_radius, double collar_radius, osg::Image* intensityMap, const osg::Matrix& projectorMatrix)
1140{
1141    osg::Vec3d center(0.0,0.0,0.0);
1142    osg::Vec3d eye(0.0,0.0,0.0);
1143   
1144    double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius);
1145    bool flip = false;
1146    bool texcoord_flip = false;
1147
1148    osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance);
1149   
1150   
1151    osg::notify(osg::INFO)<<"createParoramicSphericalDisplayDistortionMesh : Projector position = "<<projector<<std::endl;
1152    osg::notify(osg::INFO)<<"createParoramicSphericalDisplayDistortionMesh : distance = "<<distance<<std::endl;
1153
1154    // create the quad to visualize.
1155    osg::Geometry* geometry = new osg::Geometry();
1156
1157    geometry->setSupportsDisplayList(false);
1158
1159    osg::Vec3 xAxis(widthVector);
1160    float width = widthVector.length();
1161    xAxis /= width;
1162
1163    osg::Vec3 yAxis(heightVector);
1164    float height = heightVector.length();
1165    yAxis /= height;
1166   
1167    int noSteps = 160;
1168
1169    osg::Vec3Array* vertices = new osg::Vec3Array;
1170    osg::Vec2Array* texcoords0 = new osg::Vec2Array;
1171    osg::Vec2Array* texcoords1 = intensityMap==0 ? new osg::Vec2Array : 0;
1172    osg::Vec4Array* colors = new osg::Vec4Array;
1173
1174    osg::Vec3 bottom = origin;
1175    osg::Vec3 dx = xAxis*(width/((float)(noSteps-2)));
1176    osg::Vec3 dy = yAxis*(height/((float)(noSteps-1)));
1177   
1178    osg::Vec3 top = origin + yAxis*height;
1179
1180    osg::Vec3 screenCenter = origin + widthVector*0.5f + heightVector*0.5f;
1181    float screenRadius = heightVector.length() * 0.5f;
1182   
1183    geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
1184
1185    for(int i=0;i<noSteps;++i)
1186    {
1187        osg::Vec3 cursor = bottom+dy*(float)i;
1188        for(int j=0;j<noSteps;++j)
1189        {
1190            osg::Vec2 texcoord(double(i)/double(noSteps-1), double(j)/double(noSteps-1));
1191            double theta = texcoord.x() * 2.0 * osg::PI;
1192            double phi = (1.0-texcoord.y()) * osg::PI;
1193           
1194            if (texcoord_flip) texcoord.y() = 1.0f - texcoord.y();
1195
1196            osg::Vec3 pos(sin(phi)*sin(theta), sin(phi)*cos(theta), cos(phi));
1197            pos = pos*projectorMatrix;
1198           
1199            double alpha = atan2(pos.x(), pos.y());
1200            if (alpha<0.0) alpha += 2.0*osg::PI;
1201           
1202            double beta = atan2(sqrt(pos.x()*pos.x() + pos.y()*pos.y()), pos.z());
1203            if (beta<0.0) beta += 2.0*osg::PI;
1204
1205            double gamma = atan2(sqrt(double(pos.x()*pos.x() + pos.y()*pos.y())), double(pos.z()+distance));
1206            if (gamma<0.0) gamma += 2.0*osg::PI;
1207           
1208           
1209            osg::Vec3 v = screenCenter + osg::Vec3(sin(alpha)*gamma*2.0/osg::PI, -cos(alpha)*gamma*2.0/osg::PI, 0.0f)*screenRadius;
1210             
1211            if (flip)
1212                vertices->push_back(osg::Vec3(v.x(), top.y()-(v.y()-origin.y()),v.z()));
1213            else
1214                vertices->push_back(v);
1215
1216            texcoords0->push_back( texcoord );
1217       
1218            osg::Vec2 texcoord1(alpha/(2.0*osg::PI), 1.0f - beta/osg::PI);
1219            if (intensityMap)
1220            {
1221                colors->push_back(intensityMap->getColor(texcoord1));
1222            }
1223            else
1224            {
1225                colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
1226                if (texcoords1) texcoords1->push_back( texcoord1 );
1227            }
1228
1229
1230        }
1231    }
1232
1233
1234    // pass the created vertex array to the points geometry object.
1235    geometry->setVertexArray(vertices);
1236
1237    geometry->setColorArray(colors);
1238    geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
1239
1240    geometry->setTexCoordArray(0,texcoords0);
1241    if (texcoords1) geometry->setTexCoordArray(1,texcoords1);
1242
1243    osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
1244    geometry->addPrimitiveSet(elements);
1245
1246    for(int i=0;i<noSteps-1;++i)
1247    {
1248        for(int j=0;j<noSteps-1;++j)
1249        {
1250            int i1 = j+(i+1)*noSteps;
1251            int i2 = j+(i)*noSteps;
1252            int i3 = j+1+(i)*noSteps;
1253            int i4 = j+1+(i+1)*noSteps;
1254           
1255            osg::Vec3& v1 = (*vertices)[i1];
1256            osg::Vec3& v2 = (*vertices)[i2];
1257            osg::Vec3& v3 = (*vertices)[i3];
1258            osg::Vec3& v4 = (*vertices)[i4];
1259
1260            if ((v1-screenCenter).length()>screenRadius) continue;
1261            if ((v2-screenCenter).length()>screenRadius) continue;
1262            if ((v3-screenCenter).length()>screenRadius) continue;
1263            if ((v4-screenCenter).length()>screenRadius) continue;
1264           
1265            elements->push_back(i1);
1266            elements->push_back(i2);
1267            elements->push_back(i3);
1268           
1269            elements->push_back(i1);
1270            elements->push_back(i3);
1271            elements->push_back(i4);
1272        }
1273    }
1274   
1275    return geometry;
1276}
1277
1278void View::setUpViewForPanoramicSphericalDisplay(double radius, double collar, unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix)
1279{
1280    osg::notify(osg::INFO)<<"View::setUpViewForPanoramicSphericalDisplay(rad="<<radius<<", cllr="<<collar<<", sn="<<screenNum<<", im="<<intensityMap<<")"<<std::endl;
1281
1282    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
1283    if (!wsi)
1284    {
1285        osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
1286        return;
1287    }
1288
1289    osg::GraphicsContext::ScreenIdentifier si;
1290    si.readDISPLAY();
1291   
1292    // displayNum has not been set so reset it to 0.
1293    if (si.displayNum<0) si.displayNum = 0;
1294
1295    si.screenNum = screenNum;
1296
1297    unsigned int width, height;
1298    wsi->getScreenResolution(si, width, height);
1299
1300    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
1301    traits->hostName = si.hostName;
1302    traits->displayNum = si.displayNum;
1303    traits->screenNum = si.screenNum;
1304    traits->x = 0;
1305    traits->y = 0;
1306    traits->width = width;
1307    traits->height = height;
1308    traits->windowDecoration = false;
1309    traits->doubleBuffer = true;
1310    traits->sharedContext = 0;
1311   
1312
1313    bool applyIntensityMapAsColours = true;
1314
1315    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
1316    if (!gc)
1317    {
1318        osg::notify(osg::NOTICE)<<"GraphicsWindow has not been created successfully."<<std::endl;
1319        return;
1320    }
1321
1322    int tex_width = width;
1323    int tex_height = height;
1324
1325    int camera_width = tex_width;
1326    int camera_height = tex_height;
1327
1328    osg::TextureRectangle* texture = new osg::TextureRectangle;
1329
1330    texture->setTextureSize(tex_width, tex_height);
1331    texture->setInternalFormat(GL_RGB);
1332    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
1333    texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
1334    texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
1335    texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
1336   
1337#if 0   
1338    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW;
1339    GLenum buffer = GL_FRONT;
1340#else
1341    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
1342    GLenum buffer = GL_FRONT;
1343#endif
1344
1345    // front face
1346    {
1347        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1348        camera->setName("Front face camera");
1349        camera->setGraphicsContext(gc.get());
1350        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
1351        camera->setDrawBuffer(buffer);
1352        camera->setReadBuffer(buffer);
1353        camera->setAllowEventFocus(false);
1354        // tell the camera to use OpenGL frame buffer object where supported.
1355        camera->setRenderTargetImplementation(renderTargetImplementation);
1356
1357        // attach the texture and use it as the color buffer.
1358        camera->attach(osg::Camera::COLOR_BUFFER, texture);
1359
1360        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
1361    }
1362
1363    // distortion correction set up.
1364    {
1365        osg::Geode* geode = new osg::Geode();
1366        geode->addDrawable(createParoramicSphericalDisplayDistortionMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), radius, collar, applyIntensityMapAsColours ? intensityMap : 0, projectorMatrix));
1367
1368        // new we need to add the texture to the mesh, we do so by creating a
1369        // StateSet to contain the Texture StateAttribute.
1370        osg::StateSet* stateset = geode->getOrCreateStateSet();
1371        stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
1372        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
1373
1374        osg::TexMat* texmat = new osg::TexMat;
1375        texmat->setScaleByTextureRectangleSize(true);
1376        stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
1377
1378        if (!applyIntensityMapAsColours && intensityMap)
1379        {
1380            stateset->setTextureAttributeAndModes(1, new osg::Texture2D(intensityMap), osg::StateAttribute::ON);
1381        }
1382
1383        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1384        camera->setGraphicsContext(gc.get());
1385        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
1386        camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
1387        camera->setViewport(new osg::Viewport(0, 0, width, height));
1388        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
1389        camera->setDrawBuffer(buffer);
1390        camera->setReadBuffer(buffer);
1391        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
1392        camera->setAllowEventFocus(false);
1393        camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
1394        //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
1395       
1396        camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
1397        camera->setViewMatrix(osg::Matrix::identity());
1398
1399        // add subgraph to render
1400        camera->addChild(geode);
1401       
1402        camera->setName("DistortionCorrectionCamera");
1403
1404        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
1405    }
1406}
1407
1408void View::setUpViewForWoWVxDisplay(unsigned int screenNum, unsigned char wow_content, unsigned char wow_factor, unsigned char wow_offset, float wow_disparity_Zd, float wow_disparity_vz, float wow_disparity_M, float wow_disparity_C)
1409{
1410    osg::notify(osg::INFO)<<"View::setUpViewForWoWVxDisplay(...)"<<std::endl;
1411
1412    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
1413    if (!wsi)
1414    {
1415        osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
1416        return;
1417    }
1418
1419    osg::GraphicsContext::ScreenIdentifier si;
1420    si.readDISPLAY();
1421   
1422    // displayNum has not been set so reset it to 0.
1423    if (si.displayNum<0) si.displayNum = 0;
1424   
1425    si.screenNum = screenNum;
1426
1427    unsigned int width, height;
1428    wsi->getScreenResolution(si, width, height);
1429
1430    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
1431    traits->hostName = si.hostName;
1432    traits->displayNum = si.displayNum;
1433    traits->screenNum = si.screenNum;
1434    traits->x = 0;
1435    traits->y = 0;
1436    traits->width = width;
1437    traits->height = height;
1438    traits->windowDecoration = false;
1439    traits->doubleBuffer = true;
1440    traits->sharedContext = 0;
1441   
1442
1443    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
1444    if (!gc)
1445    {
1446        osg::notify(osg::NOTICE)<<"GraphicsWindow has not been created successfully."<<std::endl;
1447        return;
1448    }
1449
1450    int tex_width = width;
1451    int tex_height = height;
1452
1453    int camera_width = tex_width;
1454    int camera_height = tex_height;
1455
1456    osg::Texture2D* texture = new osg::Texture2D;
1457    texture->setTextureSize(tex_width, tex_height);
1458    texture->setInternalFormat(GL_RGB);
1459    texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
1460    texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
1461
1462    osg::Texture2D* textureD = new osg::Texture2D;
1463    textureD->setTextureSize(tex_width, tex_height);
1464    textureD->setInternalFormat(GL_DEPTH_COMPONENT);
1465    textureD->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
1466    textureD->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
1467
1468#if 0   
1469    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW;
1470    GLenum buffer = GL_FRONT;
1471#else
1472    osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
1473    GLenum buffer = GL_FRONT;
1474#endif
1475
1476    // front face
1477    {
1478        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1479        camera->setName("Front face camera");
1480        camera->setGraphicsContext(gc.get());
1481        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
1482        camera->setDrawBuffer(buffer);
1483        camera->setReadBuffer(buffer);
1484        camera->setAllowEventFocus(false);
1485        // tell the camera to use OpenGL frame buffer object where supported.
1486        camera->setRenderTargetImplementation(renderTargetImplementation);
1487
1488        // attach the texture and use it as the color buffer.
1489        camera->attach(osg::Camera::COLOR_BUFFER, texture);
1490        camera->attach(osg::Camera::DEPTH_BUFFER, textureD);
1491
1492        addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
1493    }
1494
1495    // WoW display set up.
1496    {
1497        osg::Texture1D *textureHeader = new osg::Texture1D();
1498        // Set up the header
1499        {
1500            unsigned char header[]= {0xF1,wow_content,wow_factor,wow_offset,0x00,0x00,0x00,0x00,0x00,0x00};
1501            // Calc the CRC32
1502            {
1503                unsigned long _register = 0;
1504                for(int i = 0; i < 10; ++i) {
1505                    unsigned char mask = 0x80;
1506                    unsigned char byte = header[i];
1507                    for (int j = 0; j < 8; ++j)
1508                    {
1509                        bool topBit = (_register & 0x80000000) != 0;
1510                        _register <<= 1;
1511                        _register ^= ((byte & mask) != 0? 0x1: 0x0);
1512                        if (topBit)
1513                        {
1514                            _register ^= 0x04c11db7;
1515                        }
1516                        mask >>= 1;
1517                    }
1518                }
1519                unsigned char *p = (unsigned char*) &_register;
1520                for(size_t i = 0; i < 4; ++i)
1521                {
1522                    header[i+6] = p[3-i];
1523                }
1524            }
1525
1526            osg::ref_ptr<osg::Image> imageheader = new osg::Image();
1527            imageheader->allocateImage(256,1,1,GL_LUMINANCE,GL_UNSIGNED_BYTE);
1528            {
1529                unsigned char *cheader = imageheader->data();
1530                for (int x=0; x<256; ++x){
1531                    cheader[x] = 0;
1532                }
1533                for (int x=0; x<=9; ++x){
1534                    for (int y=7; y>=0; --y){
1535                        int i = 2*(7-y)+16*x;           
1536                        cheader[i] = (((1<<(y))&(header[x])) << (7-(y)));
1537                    }
1538                }
1539            }           
1540            textureHeader->setImage(imageheader.get());
1541        }
1542
1543        // Create the Screen Aligned Quad
1544        osg::Geode* geode = new osg::Geode();
1545        {
1546            osg::Geometry* geom = new osg::Geometry;
1547
1548            osg::Vec3Array* vertices = new osg::Vec3Array;
1549            vertices->push_back(osg::Vec3(0,height,0));
1550            vertices->push_back(osg::Vec3(0,0,0));
1551            vertices->push_back(osg::Vec3(width,0,0));
1552            vertices->push_back(osg::Vec3(width,height,0));
1553            geom->setVertexArray(vertices);
1554
1555            osg::Vec2Array* tex = new osg::Vec2Array;
1556            tex->push_back(osg::Vec2(0,1));
1557            tex->push_back(osg::Vec2(0,0));
1558            tex->push_back(osg::Vec2(1,0));
1559            tex->push_back(osg::Vec2(1,1));
1560            geom->setTexCoordArray(0,tex);
1561
1562            geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
1563            geode->addDrawable(geom);
1564
1565            // new we need to add the textures to the quad, and setting up the shader.
1566            osg::StateSet* stateset = geode->getOrCreateStateSet();
1567            stateset->setTextureAttributeAndModes(0, textureHeader,osg::StateAttribute::ON);
1568            stateset->setTextureAttributeAndModes(1, texture,osg::StateAttribute::ON);
1569            stateset->setTextureAttributeAndModes(2, textureD,osg::StateAttribute::ON);
1570            stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
1571
1572            osg::ref_ptr<osg::Program> programShader = new osg::Program();
1573            stateset->setAttribute(programShader.get(), osg::StateAttribute::ON);
1574            stateset->addUniform( new osg::Uniform("wow_width", (int)width));
1575            stateset->addUniform( new osg::Uniform("wow_height", (int)height));
1576            stateset->addUniform( new osg::Uniform("wow_disparity_M", wow_disparity_M));
1577            stateset->addUniform( new osg::Uniform("wow_disparity_Zd", wow_disparity_Zd));
1578            stateset->addUniform( new osg::Uniform("wow_disparity_vz", wow_disparity_vz));
1579            stateset->addUniform( new osg::Uniform("wow_disparity_C", wow_disparity_C));
1580
1581            stateset->addUniform(new osg::Uniform("wow_header", 0));
1582            stateset->addUniform(new osg::Uniform("wow_tcolor", 1));
1583            stateset->addUniform(new osg::Uniform("wow_tdepth", 2));
1584           
1585            osg::Shader *frag = new osg::Shader(osg::Shader::FRAGMENT);
1586            frag->setShaderSource(" "\
1587                    " uniform sampler1D wow_header;                                                                                   " \
1588                    " uniform sampler2D wow_tcolor;                                                                                   " \
1589                    " uniform sampler2D wow_tdepth;                                                                                   " \
1590                    "                                                                                                                 " \
1591                    " uniform int wow_width;                                                                                          " \
1592                    " uniform int wow_height;                                                                                         " \
1593                    " uniform float wow_disparity_M;                                                                                  " \
1594                    " uniform float wow_disparity_Zd;                                                                                 " \
1595                    " uniform float wow_disparity_vz;                                                                                 " \
1596                    " uniform float wow_disparity_C;                                                                                  " \
1597                    "                                                                                                                 " \
1598                    " float disparity(float Z)                                                                                        " \
1599                    " {                                                                                                               " \
1600                    "     return (wow_disparity_M*(1.0-(wow_disparity_vz/(Z-wow_disparity_Zd+wow_disparity_vz)))                        " \
1601                    "                   + wow_disparity_C) / 255.0;                                                                   " \
1602                    " }                                                                                                               " \
1603                    "                                                                                                                 " \
1604                    " void main()                                                                                                     " \
1605                    " {                                                                                                               " \
1606                    "       vec2 pos = (gl_FragCoord.xy / vec2(wow_width/2,wow_height) );                                             " \
1607                    "         if (gl_FragCoord.x > float(wow_width/2))                                                                  " \
1608                    "         {                                                                                                         " \
1609                    "             gl_FragColor = vec4(disparity(( texture2D(wow_tdepth, pos - vec2(1,0))).z));                          " \
1610                    "         }                                                                                                         " \
1611                    "         else{                                                                                                     " \
1612                    "             gl_FragColor = texture2D(wow_tcolor, pos);                                                            " \
1613                    "         }                                                                                                         " \
1614                    "     if ( (gl_FragCoord.y >= float(wow_height-1)) && (gl_FragCoord.x < 256.0) )                                    " \
1615                    "     {                                                                                                             " \
1616                    "         float pos = gl_FragCoord.x/256.0;                                                                         " \
1617                    "         float blue = texture1D(wow_header, pos).b;                                                                " \
1618                    "         if ( blue < 0.5)                                                                                          " \
1619                    "             gl_FragColor.b = 0.0;                                                                                 " \
1620                    "         else                                                                                                      " \
1621                    "             gl_FragColor.b = 1.0;                                                                                 " \
1622                    "     }                                                                                                             " \
1623                    " }                                                                                                               " );
1624
1625            programShader->addShader(frag);
1626        }
1627
1628        // Create the Camera
1629        {
1630            osg::ref_ptr<osg::Camera> camera = new osg::Camera;
1631            camera->setGraphicsContext(gc.get());
1632            camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
1633            camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
1634            camera->setViewport(new osg::Viewport(0, 0, width, height));
1635            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
1636            camera->setDrawBuffer(buffer);
1637            camera->setReadBuffer(buffer);
1638            camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
1639            camera->setAllowEventFocus(false);
1640            camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
1641            //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
1642           
1643            camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
1644            camera->setViewMatrix(osg::Matrix::identity());
1645
1646            // add subgraph to render
1647            camera->addChild(geode);
1648           
1649            camera->setName("WoWCamera");
1650
1651            addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
1652        }
1653    }
1654}
1655
1656
1657
1658void View::assignSceneDataToCameras()
1659{
1660    // osg::notify(osg::NOTICE)<<"View::assignSceneDataToCameras()"<<std::endl;
1661
1662    osg::Node* sceneData = _scene.valid() ? _scene->getSceneData() : 0;
1663   
1664    if (_cameraManipulator.valid())
1665    {
1666        _cameraManipulator->setNode(sceneData);
1667       
1668        osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();
1669
1670        _cameraManipulator->home(*dummyEvent, *this);
1671    }
1672
1673    if (_camera.valid())
1674    {
1675        _camera->removeChildren(0,_camera->getNumChildren());
1676        if (sceneData) _camera->addChild(sceneData);
1677       
1678        Renderer* renderer = dynamic_cast<Renderer*>(_camera->getRenderer());
1679        if (renderer) renderer->setCompileOnNextDraw(true);
1680
1681    }
1682
1683    for(unsigned i=0; i<getNumSlaves(); ++i)
1684    {
1685        Slave& slave = getSlave(i);
1686        if (slave._camera.valid() && slave._useMastersSceneData)
1687        {
1688            slave._camera->removeChildren(0,slave._camera->getNumChildren());
1689            if (sceneData) slave._camera->addChild(sceneData);
1690       
1691            Renderer* renderer = dynamic_cast<Renderer*>(slave._camera->getRenderer());
1692            if (renderer) renderer->setCompileOnNextDraw(true);
1693        }
1694    }   
1695}
1696
1697void View::requestRedraw()
1698{
1699}
1700
1701void View::requestContinuousUpdate(bool)
1702{
1703}
1704
1705void View::requestWarpPointer(float x,float y)
1706{
1707    osg::notify(osg::INFO)<<"View::requestWarpPointer("<<x<<","<<y<<")"<<std::endl;
1708   
1709    float local_x, local_y;
1710    const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
1711    if (camera)
1712    {
1713        const osgViewer::GraphicsWindow* gw = dynamic_cast<const osgViewer::GraphicsWindow*>(camera->getGraphicsContext());
1714        if (gw)
1715        {
1716            getEventQueue()->mouseWarped(x,y);
1717            if (gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS)
1718            {
1719                local_y = gw->getTraits()->height - local_y;
1720            }
1721            const_cast<osgViewer::GraphicsWindow*>(gw)->getEventQueue()->mouseWarped(local_x,local_y);
1722            const_cast<osgViewer::GraphicsWindow*>(gw)->requestWarpPointer(local_x, local_y);
1723        }
1724    }
1725    else
1726    {
1727        osg::notify(osg::INFO)<<"View::requestWarpPointer failed no camera containing pointer"<<std::endl;
1728    }
1729}
1730
1731bool View::containsCamera(const osg::Camera* camera) const
1732{
1733    if (_camera == camera) return true;
1734   
1735    for(unsigned i=0; i<getNumSlaves(); ++i)
1736    {
1737        const Slave& slave = getSlave(i);
1738        if (slave._camera == camera) return true;
1739    }
1740    return false;
1741}
1742
1743const osg::Camera* View::getCameraContainingPosition(float x, float y, float& local_x, float& local_y) const
1744{
1745    const osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1746    const osgViewer::GraphicsWindow* gw = dynamic_cast<const osgViewer::GraphicsWindow*>(eventState->getGraphicsContext());
1747
1748    bool view_invert_y = eventState->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
1749
1750    double epsilon = 0.5;
1751
1752    if (_camera->getGraphicsContext() &&
1753        (!gw || _camera->getGraphicsContext()==gw) &&
1754        _camera->getViewport())
1755    {
1756        const osg::Viewport* viewport = _camera->getViewport();
1757       
1758        double new_x = x;
1759        double new_y = y;
1760
1761        if (!gw)
1762        {
1763            new_x = static_cast<double>(_camera->getGraphicsContext()->getTraits()->width) * (x - eventState->getXmin())/(eventState->getXmax()-eventState->getXmin());
1764            new_y = view_invert_y ?
1765                       static_cast<double>(_camera->getGraphicsContext()->getTraits()->height) * (1.0 - (y- eventState->getYmin())/(eventState->getYmax()-eventState->getYmin())) :
1766                       static_cast<double>(_camera->getGraphicsContext()->getTraits()->height) * (y - eventState->getYmin())/(eventState->getYmax()-eventState->getXmin());
1767        }
1768       
1769        if (viewport &&
1770            new_x >= (viewport->x()-epsilon) && new_y >= (viewport->y()-epsilon) &&
1771            new_x < (viewport->x()+viewport->width()-1.0+epsilon) && new_y <= (viewport->y()+viewport->height()-1.0+epsilon) )
1772        {
1773            local_x = new_x;
1774            local_y = new_y;
1775
1776            osg::notify(osg::INFO)<<"Returning master camera"<<std::endl;
1777
1778            return _camera.get();
1779        }
1780    }
1781
1782    osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
1783   
1784    // convert to non dimensional
1785    x = (x - eventState->getXmin()) * 2.0 / (eventState->getXmax()-eventState->getXmin()) - 1.0;
1786    y = (y - eventState->getYmin())* 2.0 / (eventState->getYmax()-eventState->getYmin()) - 1.0;
1787
1788    if (view_invert_y) y = - y;
1789   
1790    for(int i=getNumSlaves()-1; i>=0; --i)
1791    {
1792        const Slave& slave = getSlave(i);
1793        if (slave._camera.valid() &&
1794            slave._camera->getAllowEventFocus() &&
1795            slave._camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
1796        {
1797            osg::notify(osg::INFO)<<"Testing slave camera "<<slave._camera->getName()<<std::endl;
1798
1799            const osg::Camera* camera = slave._camera.get();
1800            const osg::Viewport* viewport = camera ? camera->getViewport() : 0;
1801
1802            osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
1803            if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
1804
1805            osg::Matrix matrix( osg::Matrix::inverse(masterCameraVPW) * localCameraVPW );
1806
1807            osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
1808
1809            //osg::notify(osg::NOTICE)<<"  x="<<x<<" y="<<y<<std::endl;;
1810            //osg::notify(osg::NOTICE)<<"  eventState->getXmin()="<<eventState->getXmin()<<" eventState->getXmax()="<<eventState->getXmax()<<std::endl;;
1811            //osg::notify(osg::NOTICE)<<"  new_coord "<<new_coord<<std::endl;;
1812
1813            if (viewport &&
1814                new_coord.x() >= (viewport->x()-epsilon) && new_coord.y() >= (viewport->y()-epsilon) &&
1815                new_coord.x() < (viewport->x()+viewport->width()-1.0+epsilon) && new_coord.y() <= (viewport->y()+viewport->height()-1.0+epsilon) )
1816            {
1817                // osg::notify(osg::NOTICE)<<"  in viewport "<<std::endl;;
1818               
1819                local_x = new_coord.x();
1820                local_y = new_coord.y();
1821
1822                return camera;
1823            }
1824            else
1825            {
1826                // osg::notify(osg::NOTICE)<<"  not in viewport "<<viewport->x()<<" "<<(viewport->x()+viewport->width())<<std::endl;;
1827            }
1828
1829        }
1830    }
1831   
1832    local_x = x;
1833    local_y = y;
1834   
1835    return 0;
1836}
1837
1838bool View::computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections, osg::Node::NodeMask traversalMask)
1839{
1840    if (!_camera.valid()) return false;
1841
1842    float local_x, local_y = 0.0;   
1843    const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
1844    if (!camera) camera = _camera.get();
1845   
1846
1847    osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
1848    osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
1849
1850#if 0
1851    osg::notify(osg::NOTICE)<<"View::computeIntersections(x="<<x<<", y="<<y<<", local_x="<<local_x<<", local_y="<<local_y<<") "<<cf<<std::endl;
1852    osg::notify(osg::NOTICE)<<"  viewport ("<<camera->getViewport()->x()<<","<<camera->getViewport()->y()<<","<<camera->getViewport()->width()<<","<<camera->getViewport()->height()<<")"<<std::endl;
1853
1854    const osg::GraphicsContext::Traits* traits = camera->getGraphicsContext() ? camera->getGraphicsContext()->getTraits() : 0;
1855    if (traits)
1856    {
1857        osg::notify(osg::NOTICE)<<"  window ("<<traits->x<<","<<traits->y<<","<<traits->width<<","<<traits->height<<")"<<std::endl;
1858    }
1859#endif
1860
1861    osgUtil::IntersectionVisitor iv(picker.get());
1862    iv.setTraversalMask(traversalMask);
1863   
1864   
1865#if 1
1866    const_cast<osg::Camera*>(camera)->accept(iv);
1867#else   
1868
1869    // timing test code paths for comparing KdTree based intersections vs conventional intersections
1870
1871    iv.setUseKdTreeWhenAvailable(true);
1872    iv.setDoDummyTraversal(true);
1873
1874    const_cast<osg::Camera*>(camera)->accept(iv);
1875   
1876
1877    osg::Timer_t before = osg::Timer::instance()->tick();
1878    const_cast<osg::Camera*>(camera)->accept(iv);
1879
1880    osg::Timer_t after_dummy = osg::Timer::instance()->tick();
1881
1882    int intersectsBeforeKdTree = picker->getIntersections().size();
1883
1884    iv.setDoDummyTraversal(false);
1885    const_cast<osg::Camera*>(camera)->accept(iv);
1886    osg::Timer_t after_kdTree_2 = osg::Timer::instance()->tick();
1887
1888    int intersectsBeforeConventional = picker->getIntersections().size();
1889
1890    iv.setUseKdTreeWhenAvailable(false);
1891    const_cast<osg::Camera*>(camera)->accept(iv);
1892    osg::Timer_t after = osg::Timer::instance()->tick();
1893   
1894    int intersectsAfterConventional = picker->getIntersections().size();
1895
1896    double timeDummy = osg::Timer::instance()->delta_m(before, after_dummy);
1897    double timeKdTree = osg::Timer::instance()->delta_m(after_dummy, after_kdTree_2);
1898    double timeConventional = osg::Timer::instance()->delta_m(after_kdTree_2, after);
1899   
1900    osg::notify(osg::NOTICE)<<"Using Dummy                    "<<timeDummy<<std::endl;
1901    osg::notify(osg::NOTICE)<<"      KdTrees                  "<<timeKdTree
1902                            <<"\tNum intersects = "<<intersectsBeforeConventional-intersectsBeforeKdTree<<std::endl;
1903    osg::notify(osg::NOTICE)<<"      KdTrees - Traversal      "<<timeKdTree-timeDummy<<std::endl;
1904    osg::notify(osg::NOTICE)<<"      Conventional             "<<timeConventional
1905                            <<"\tNum intersects = "<<intersectsAfterConventional-intersectsBeforeConventional<<std::endl;
1906    osg::notify(osg::NOTICE)<<"      Conventional - Traversal "<<timeConventional-timeDummy<<std::endl;
1907    osg::notify(osg::NOTICE)<<"      Delta                    "<<timeConventional/timeKdTree<<std::endl;
1908    osg::notify(osg::NOTICE)<<"      Delta sans Traversal     "<<(timeConventional-timeDummy)/(timeKdTree-timeDummy)<<std::endl;
1909    osg::notify(osg::NOTICE)<<std::endl;
1910#endif   
1911
1912    if (picker->containsIntersections())
1913    {
1914        intersections = picker->getIntersections();
1915        return true;
1916    }
1917    else
1918    {
1919        intersections.clear();
1920        return false;
1921    }
1922}
1923
1924bool View::computeIntersections(float x,float y, const osg::NodePath& nodePath, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask)
1925{
1926    if (!_camera.valid() || nodePath.empty()) return false;
1927   
1928    float local_x, local_y = 0.0;   
1929    const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
1930    if (!camera) camera = _camera.get();
1931   
1932    osg::Matrixd matrix;
1933    if (nodePath.size()>1)
1934    {
1935        osg::NodePath prunedNodePath(nodePath.begin(),nodePath.end()-1);
1936        matrix = osg::computeLocalToWorld(prunedNodePath);
1937    }
1938   
1939    matrix.postMult(camera->getViewMatrix());
1940    matrix.postMult(camera->getProjectionMatrix());
1941
1942    double zNear = -1.0;
1943    double zFar = 1.0;
1944    if (camera->getViewport())
1945    {
1946        matrix.postMult(camera->getViewport()->computeWindowMatrix());
1947        zNear = 0.0;
1948        zFar = 1.0;
1949    }
1950
1951    osg::Matrixd inverse;
1952    inverse.invert(matrix);
1953
1954    osg::Vec3d startVertex = osg::Vec3d(local_x,local_y,zNear) * inverse;
1955    osg::Vec3d endVertex = osg::Vec3d(local_x,local_y,zFar) * inverse;
1956   
1957    osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::MODEL, startVertex, endVertex);
1958   
1959    osgUtil::IntersectionVisitor iv(picker.get());
1960    iv.setTraversalMask(traversalMask);
1961    nodePath.back()->accept(iv);
1962
1963    if (picker->containsIntersections())
1964    {
1965        intersections = picker->getIntersections();
1966        return true;
1967    }
1968    else
1969    {
1970        intersections.clear();
1971        return false;
1972    }
1973}
Note: See TracBrowser for help on using the browser.