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

Revision 13202, 81.8 kB (checked in by robert, 14 hours ago)

Changed osgvolume example to use the new tf plugin rather than having local code for reading transfer function

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