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

Revision 10764, 73.6 kB (checked in by robert, 5 years ago)

<iterator>, <stdlib.h> and <ctype.h> includes required for QNX compiler

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