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

Revision 9462, 75.0 kB (checked in by robert, 5 years ago)

Added handling of when a View isn't yet assigned to a Viewer to avoid associated crash

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