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

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

From Mathias Froehlich, "This is a generic optimization that does not depend on any cpu or instruction
set.

The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 43 Operations whereas multiplication with a
transform, or scale matrix is only 4
2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.

Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform? is about 20% slower
than the same codepath using the PositionAttitudeTransform? instead of the
MatrixTransform? with this patch applied.

If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.

An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"

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