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

Revision 9892, 75.1 kB (checked in by robert, 6 years ago)

From Konstantin Matveyev, submitted by Valery Bickov:

"There is error in WoW shader, you can see it by this simple example:
osgviewer cessna.osg --wowvx-42 --clear-color 0,0,0

Clear color may be choosed any with at least one component equals to 0
or 1. In my case I see weird blinking between normal image and image
with depth map at right side on the screen."

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