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

Revision 8633, 74.3 kB (checked in by robert, 6 years ago)

First cut of osgDB::ImagePager? for updating osg::ImageSequence?

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