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

Revision 10749, 73.6 kB (checked in by robert, 4 years ago)

Added dummy StateSet? at top of scene graph when using ShaderGen? to copy with subgrahs that contain no StateSet?

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