root/OpenSceneGraph/trunk/src/osgViewer/ViewerEventHandlers.cpp @ 10415

Revision 10415, 26.7 kB (checked in by robert, 5 years ago)

From Mathias Froehlich, "We are currently getting issues with locale settings and some osg plugins.
Therefore I have changed all the occurances of atof by asciiToFloat or
asciiToDouble.

I believe that it is safe to do so at least for all the plugins.
Included here are also asciiToFloat conversion of environment variables. One
might argue that these should be locale dependent. But IMO these should be
set and interpreted by osg independent of the current locale.
"

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 <stdlib.h>
15#include <float.h>
16#include <limits.h>
17
18#include <iomanip>
19#include <sstream>
20
21#include <osgDB/FileNameUtils>
22
23#include <osg/Geometry>
24#include <osg/TexMat>
25#include <osg/TextureRectangle>
26#include <osg/io_utils>
27
28#include <osgViewer/Viewer>
29#include <osgViewer/ViewerEventHandlers>
30
31namespace osgViewer
32{
33
34/*
35** WindowSizeHandler
36*/
37
38WindowSizeHandler::WindowSizeHandler() :
39    _keyEventToggleFullscreen('f'),
40    _toggleFullscreen(true),
41    _keyEventWindowedResolutionUp('>'),
42    _keyEventWindowedResolutionDown('<'),
43    _changeWindowedResolution(true),
44    _currentResolutionIndex(-1)
45{
46    _resolutionList.push_back(osg::Vec2(640, 480));
47    _resolutionList.push_back(osg::Vec2(800, 600));
48    _resolutionList.push_back(osg::Vec2(1024, 768));
49    _resolutionList.push_back(osg::Vec2(1152, 864));
50    _resolutionList.push_back(osg::Vec2(1280, 720));
51    _resolutionList.push_back(osg::Vec2(1280, 768));
52    _resolutionList.push_back(osg::Vec2(1280, 1024));
53    _resolutionList.push_back(osg::Vec2(1440, 900));
54    _resolutionList.push_back(osg::Vec2(1400, 1050));
55    _resolutionList.push_back(osg::Vec2(1600, 900));
56    _resolutionList.push_back(osg::Vec2(1600, 1024));
57    _resolutionList.push_back(osg::Vec2(1600, 1200));
58    _resolutionList.push_back(osg::Vec2(1680, 1050));
59    _resolutionList.push_back(osg::Vec2(1920, 1080));
60    _resolutionList.push_back(osg::Vec2(1920, 1200));
61    _resolutionList.push_back(osg::Vec2(2048, 1536));
62    _resolutionList.push_back(osg::Vec2(2560, 2048));
63    _resolutionList.push_back(osg::Vec2(3200, 2400));
64    _resolutionList.push_back(osg::Vec2(3840, 2400));
65}
66
67void WindowSizeHandler::getUsage(osg::ApplicationUsage &usage) const
68{
69    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventToggleFullscreen), "Toggle full screen.");
70    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventWindowedResolutionUp), "Increase the screen resolution (in windowed mode).");
71    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventWindowedResolutionDown), "Decrease the screen resolution (in windowed mode).");
72}
73
74bool WindowSizeHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
75{
76    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
77    if (!view) return false;
78   
79    osgViewer::ViewerBase* viewer = view->getViewerBase();
80
81    if (viewer == NULL)
82    {
83        return false;
84    }
85
86    if (ea.getHandled()) return false;
87
88    switch(ea.getEventType())
89    {
90        case(osgGA::GUIEventAdapter::KEYUP):
91        {
92            if (_toggleFullscreen == true && ea.getKey() == _keyEventToggleFullscreen)
93            {
94                osgViewer::Viewer::Windows    windows;
95
96                viewer->getWindows(windows);
97                for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
98                    itr != windows.end();
99                    ++itr)
100                {
101                    toggleFullscreen(*itr);
102                }
103
104                aa.requestRedraw();
105                return true;
106            }
107            else if (_changeWindowedResolution == true && ea.getKey() == _keyEventWindowedResolutionUp)
108            {
109                // Increase resolution
110                osgViewer::Viewer::Windows    windows;
111
112                viewer->getWindows(windows);
113                for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
114                    itr != windows.end();
115                    ++itr)
116                {
117                    changeWindowedResolution(*itr, true);
118                }
119
120                aa.requestRedraw();
121                return true;
122            }
123            else if (_changeWindowedResolution == true && ea.getKey() == _keyEventWindowedResolutionDown)
124            {
125                // Decrease resolution
126                osgViewer::Viewer::Windows    windows;
127
128                viewer->getWindows(windows);
129                for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
130                    itr != windows.end();
131                    ++itr)
132                {
133                    changeWindowedResolution(*itr, false);
134                }
135
136                aa.requestRedraw();
137                return true;
138            }
139            break;
140        }
141    default:
142        break;
143    }
144    return false;
145}
146
147void WindowSizeHandler::toggleFullscreen(osgViewer::GraphicsWindow *window)
148{
149    osg::GraphicsContext::WindowingSystemInterface    *wsi = osg::GraphicsContext::getWindowingSystemInterface();
150
151    if (wsi == NULL)
152    {
153        osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
154        return;
155    }
156
157    unsigned int    screenWidth;
158    unsigned int    screenHeight;
159
160    wsi->getScreenResolution(*(window->getTraits()), screenWidth, screenHeight);
161
162    int x;
163    int y;
164    int width;
165    int height;
166
167    window->getWindowRectangle(x, y, width, height);
168
169    bool    isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight;
170
171    if (isFullScreen)
172    {
173        osg::Vec2    resolution;
174
175        if (_currentResolutionIndex == -1)
176        {
177            _currentResolutionIndex = getNearestResolution(screenWidth, screenHeight, screenWidth / 2, screenHeight / 2);
178        }
179        resolution = _resolutionList[_currentResolutionIndex];
180        window->setWindowDecoration(true);
181        window->setWindowRectangle((screenWidth - (int)resolution.x()) / 2, (screenHeight - (int)resolution.y()) / 2, (int)resolution.x(), (int)resolution.y());
182        osg::notify(osg::INFO) << "Screen resolution = " << (int)resolution.x() << "x" << (int)resolution.y() << std::endl; 
183    }
184    else
185    {
186        window->setWindowDecoration(false);
187        window->setWindowRectangle(0, 0, screenWidth, screenHeight);
188    }
189
190    window->grabFocusIfPointerInWindow();
191}
192
193void WindowSizeHandler::changeWindowedResolution(osgViewer::GraphicsWindow *window, bool increase)
194{
195    osg::GraphicsContext::WindowingSystemInterface    *wsi = osg::GraphicsContext::getWindowingSystemInterface();
196
197    if (wsi == NULL)
198    {
199        osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
200        return;
201    }
202
203    unsigned int    screenWidth;
204    unsigned int    screenHeight;
205
206    wsi->getScreenResolution(*(window->getTraits()), screenWidth, screenHeight);
207
208    int x;
209    int y;
210    int width;
211    int height;
212
213    window->getWindowRectangle(x, y, width, height);
214
215    bool    isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight;
216
217    if (window->getWindowDecoration() == true || isFullScreen == false)
218    {
219        osg::Vec2    resolution;
220
221        if (_currentResolutionIndex == -1)
222        {
223            _currentResolutionIndex = getNearestResolution(screenWidth, screenHeight, width, height);
224        }
225
226        if (increase == true)
227        {
228            // Find the next resolution
229            for (int i = _currentResolutionIndex + 1; i < (int)_resolutionList.size(); ++i)
230            {
231                if ((unsigned int)_resolutionList[i].x() <= screenWidth && (unsigned int)_resolutionList[i].y() <= screenHeight)
232                {
233                    _currentResolutionIndex = i;
234                    break;
235                }
236            }
237        }
238        else
239        {
240            // Find the previous resolution
241            for (int i = _currentResolutionIndex - 1; i >= 0; --i)
242            {
243                if ((unsigned int)_resolutionList[i].x() <= screenWidth && (unsigned int)_resolutionList[i].y() <= screenHeight)
244                {
245                    _currentResolutionIndex = i;
246                    break;
247                }
248            }
249        }
250
251        resolution = _resolutionList[_currentResolutionIndex];
252        window->setWindowDecoration(true);
253        window->setWindowRectangle((screenWidth - (int)resolution.x()) / 2, (screenHeight - (int)resolution.y()) / 2, (int)resolution.x(), (int)resolution.y());
254        osg::notify(osg::INFO) << "Screen resolution = " << (int)resolution.x() << "x" << (int)resolution.y() << std::endl; 
255
256        window->grabFocusIfPointerInWindow();
257    }
258}
259
260unsigned int WindowSizeHandler::getNearestResolution(int screenWidth, int screenHeight, int width, int height) const
261{
262    unsigned int    position = 0;
263    unsigned int    result = 0;
264    int                delta = INT_MAX;
265
266    for (std::vector<osg::Vec2>::const_iterator it = _resolutionList.begin();
267        it != _resolutionList.end();
268        ++it, ++position)
269    {
270        if ((int)it->x() <= screenWidth && (int)it->y() <= screenHeight)
271        {
272            int tmp = static_cast<int>(osg::absolute((width * height) - (it->x() * it->y())));
273
274            if (tmp < delta)
275            {
276                delta = tmp;
277                result = position;
278            }
279        }
280    }
281    return (result);
282}
283
284/*
285** ThreadingHandler
286*/
287
288ThreadingHandler::ThreadingHandler() :
289    _keyEventChangeThreadingModel('m'),
290    _changeThreadingModel(true),
291    _keyEventChangeEndBarrierPosition('e'),
292    _changeEndBarrierPosition(true)
293{
294    _tickOrLastKeyPress = osg::Timer::instance()->tick();
295}
296
297void ThreadingHandler::getUsage(osg::ApplicationUsage &usage) const
298{
299    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventChangeThreadingModel), "Toggle threading model.");
300    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventChangeEndBarrierPosition), "Toggle the placement of the end of frame barrier.");
301}
302
303bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
304{
305    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
306    if (!view) return false;
307   
308    osgViewer::ViewerBase* viewerBase = view->getViewerBase();
309    osgViewer::Viewer* viewer = dynamic_cast<Viewer*>(viewerBase);
310
311    if (viewerBase == NULL)
312    {
313        return false;
314    }
315
316    if (ea.getHandled()) return false;
317
318    switch(ea.getEventType())
319    {
320        case(osgGA::GUIEventAdapter::KEYUP):
321        {
322            double    delta = osg::Timer::instance()->delta_s(_tickOrLastKeyPress, osg::Timer::instance()->tick());
323
324            if (_changeThreadingModel == true && ea.getKey() == _keyEventChangeThreadingModel && delta > 1.0)
325            {
326
327                _tickOrLastKeyPress = osg::Timer::instance()->tick();
328
329                switch(viewerBase->getThreadingModel())
330                {
331                case(osgViewer::ViewerBase::SingleThreaded):
332                    viewerBase->setThreadingModel(osgViewer::ViewerBase::CullDrawThreadPerContext);
333                    osg::notify(osg::NOTICE)<<"Threading model 'CullDrawThreadPerContext' selected."<<std::endl;
334                    break;
335                case(osgViewer::ViewerBase::CullDrawThreadPerContext):
336                    viewerBase->setThreadingModel(osgViewer::ViewerBase::DrawThreadPerContext);
337                    osg::notify(osg::NOTICE)<<"Threading model 'DrawThreadPerContext' selected."<<std::endl;
338                    break;
339                case(osgViewer::ViewerBase::DrawThreadPerContext):
340                    viewerBase->setThreadingModel(osgViewer::ViewerBase::CullThreadPerCameraDrawThreadPerContext);
341                    osg::notify(osg::NOTICE)<<"Threading model 'CullThreadPerCameraDrawThreadPerContext' selected."<<std::endl;
342                    break;
343                case(osgViewer::ViewerBase::CullThreadPerCameraDrawThreadPerContext):
344                    viewerBase->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
345                    osg::notify(osg::NOTICE)<<"Threading model 'SingleThreaded' selected."<<std::endl;
346                    break;
347#if 1                   
348                case(osgViewer::ViewerBase::AutomaticSelection):
349                    viewerBase->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
350                    osg::notify(osg::NOTICE)<<"Threading model 'SingleThreaded' selected."<<std::endl;
351#else                   
352                case(osgViewer::ViewerBase::AutomaticSelection):
353                    viewerBase->setThreadingModel(viewer->suggestBestThreadingModel());
354                    osg::notify(osg::NOTICE)<<"Threading model 'AutomaticSelection' selected."<<std::endl;
355#endif
356                    break;
357                }
358
359                aa.requestRedraw();
360                return true;
361            }
362            if (viewer && _changeEndBarrierPosition == true && ea.getKey() == _keyEventChangeEndBarrierPosition)
363            {
364                switch(viewer->getEndBarrierPosition())
365                {
366                case(osgViewer::Viewer::BeforeSwapBuffers):
367                    viewer->setEndBarrierPosition(osgViewer::Viewer::AfterSwapBuffers);
368                    osg::notify(osg::NOTICE)<<"Threading model 'AfterSwapBuffers' selected."<<std::endl;
369                    break;
370                case(osgViewer::Viewer::AfterSwapBuffers):
371                    viewer->setEndBarrierPosition(osgViewer::Viewer::BeforeSwapBuffers);
372                    osg::notify(osg::NOTICE)<<"Threading model 'BeforeSwapBuffers' selected."<<std::endl;
373                    break;
374                }
375
376                aa.requestRedraw();
377                return true;
378            }
379            break;
380        }
381    default:
382        break;
383    }
384    return false;
385}
386
387RecordCameraPathHandler::RecordCameraPathHandler(const std::string& filename, float fps):
388    _filename(filename),
389    _autoinc( -1 ),
390    _keyEventToggleRecord('z'),
391    _keyEventTogglePlayback('Z'),
392    _currentlyRecording(false),
393    _currentlyPlaying(false),
394    _delta(0.0f),
395    _animStartTime(0),
396    _lastFrameTime(osg::Timer::instance()->tick())
397{
398    _animPath = new osg::AnimationPath();
399
400    const char* str = getenv("OSG_RECORD_CAMERA_PATH_FPS");
401    if (str)
402    {
403        _interval = 1.0f / osg::asciiToDouble(str);
404    }
405    else
406    {
407        _interval = 1.0f / fps;
408    }
409}
410
411void RecordCameraPathHandler::getUsage(osg::ApplicationUsage &usage) const
412{
413    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventToggleRecord), "Toggle camera path recording.");
414    usage.addKeyboardMouseBinding(reinterpret_cast<const char*>(&_keyEventTogglePlayback), "Toggle camera path playback.");
415}
416
417bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
418{
419    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
420
421    if (view == NULL)
422    {
423        return false;
424    }
425
426    if(ea.getEventType()==osgGA::GUIEventAdapter::FRAME)
427    {
428        // Calculate our current delta (difference) in time between the last frame and
429        // current frame, regardless of whether we actually store a ControlPoint...
430        osg::Timer_t time = osg::Timer::instance()->tick();
431        double delta = osg::Timer::instance()->delta_s(_lastFrameTime, time);
432        _lastFrameTime = time;
433
434        // If our internal _delta is finally large enough to warrant a ControlPoint
435        // insertion, do so now. Be sure and reset the internal _delta, so we can start
436        // calculating when the next insert should happen.
437        if (_currentlyRecording && _delta >= _interval)
438        {
439            const osg::Matrixd& m = view->getCamera()->getInverseViewMatrix();
440            double animationPathTime = osg::Timer::instance()->delta_s(_animStartTime, time);           
441            _animPath->insert(animationPathTime, osg::AnimationPath::ControlPoint(m.getTrans(), m.getRotate()));
442            _delta = 0.0f;
443
444            if (_fout)
445            {
446                _animPath->write(_animPath->getTimeControlPointMap().find(animationPathTime), _fout);
447                _fout.flush();
448            }
449
450        }
451        else _delta += delta;
452       
453        return true;
454    }
455
456    if (ea.getHandled()) return false;
457
458    switch(ea.getEventType())
459    {
460        case(osgGA::GUIEventAdapter::KEYUP):
461        {
462            // The user has requested to toggle recording.
463            if (ea.getKey() ==_keyEventToggleRecord)
464            {
465                // The user has requested to BEGIN recording.
466                if (!_currentlyRecording)
467                {
468                    _currentlyRecording = true;
469                    _animStartTime = osg::Timer::instance()->tick();
470                    _animPath->clear();
471                   
472                    if (!_filename.empty())
473                    {
474                        std::stringstream ss;
475                        ss << osgDB::getNameLessExtension(_filename);
476                        if ( _autoinc != -1 )
477                        {
478                            ss << "_"<<std::setfill( '0' ) << std::setw( 2 ) << _autoinc;
479                            _autoinc++;
480                        }
481                        ss << "."<<osgDB::getFileExtension(_filename);
482                       
483                        osg::notify(osg::NOTICE) << "Recording camera path to file " << ss.str() << std::endl;
484                        _fout.open( ss.str().c_str() );
485
486                        // make sure doubles are not trucated by default stream precision = 6
487                        _fout.precision( 15 );
488                    }
489                    else
490                    {
491                        osg::notify(osg::NOTICE)<<"Recording camera path."<<std::endl;
492                    }
493                }
494
495                // The user has requested to STOP recording, write the file!
496                else
497                {
498                    _currentlyRecording = false;
499                    _delta = 0.0f;
500
501                    if (_fout) _fout.close();
502                }
503
504                return true;
505            }
506
507            // The user has requested to toggle playback. You'll notice in the code below that
508            // we take over the current manipulator; it was originally recommended that we
509            // check for a KeySwitchManipulator, create one if not present, and then add this
510            // to either the newly created one or the existing one. However, the code do that was
511            // EXTREMELY dirty, so I opted for a simpler solution. At a later date, someone may
512            // want to implement the original recommendation (which is in a mailing list reply
513            // from June 1st by Robert in a thread called "osgviewer Camera Animation (preliminary)".
514            else if (ea.getKey() == _keyEventTogglePlayback)
515            {
516                if (_currentlyRecording)
517                {
518                    _currentlyRecording = false;
519                    _delta = 0.0f;
520
521                    // In the future this will need to be written continuously, rather
522                    // than all at once.
523                    osgDB::ofstream out(_filename.c_str());
524                    osg::notify(osg::NOTICE)<<"Writing camera file: "<<_filename<<std::endl;
525                    _animPath->write(out);
526                    out.close();
527                }
528
529                // The user has requested to BEGIN playback.
530                if (!_currentlyPlaying)
531                {
532                    _animPathManipulator = new osgGA::AnimationPathManipulator(_animPath.get());
533                    _animPathManipulator->home(ea,aa);
534
535
536                    // If we successfully found our _filename file, set it and keep a copy
537                    // around of the original MatrixManipulator to restore later.
538                    if (_animPathManipulator.valid() && _animPathManipulator->valid())
539                    {
540                        _oldManipulator = view->getCameraManipulator();
541                        view->setCameraManipulator(_animPathManipulator.get());
542                        _currentlyPlaying = true;
543                    }
544                }
545
546                // The user has requested to STOP playback.
547                else
548                {
549                    // Restore the old manipulator if necessary and stop playback.
550                    if(_oldManipulator.valid()) view->setCameraManipulator(_oldManipulator.get());
551                    _currentlyPlaying = false;
552                    _oldManipulator = 0;
553                }
554
555                return true;
556            }       
557
558            break;
559        }
560    default:
561        break;
562    }
563
564    return false;
565}
566
567LODScaleHandler::LODScaleHandler():
568    _keyEventIncreaseLODScale('*'),
569    _keyEventDecreaseLODScale('/')
570{
571}
572
573bool LODScaleHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
574{
575    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
576    osg::Camera* camera = view ? view->getCamera() : 0;
577    if (!camera) return false;
578
579    if (ea.getHandled()) return false;
580
581    switch(ea.getEventType())
582    {
583        case(osgGA::GUIEventAdapter::KEYUP):
584        {
585            if (ea.getKey() == _keyEventIncreaseLODScale)
586            {
587                camera->setLODScale(camera->getLODScale()*1.1);
588                osg::notify(osg::NOTICE)<<"LODScale = "<<camera->getLODScale()<<std::endl;
589
590                aa.requestRedraw();
591                return true;
592            }
593
594            else if (ea.getKey() == _keyEventDecreaseLODScale)
595            {
596                camera->setLODScale(camera->getLODScale()/1.1);
597                osg::notify(osg::NOTICE)<<"LODScale = "<<camera->getLODScale()<<std::endl;
598
599                aa.requestRedraw();
600                return true;
601            }
602
603            break;
604        }
605    default:
606        break;
607    }
608
609    return false;
610}
611
612void LODScaleHandler::getUsage(osg::ApplicationUsage& usage) const
613{
614    {
615        std::ostringstream ostr;
616        ostr<<char(_keyEventIncreaseLODScale);
617        usage.addKeyboardMouseBinding(ostr.str(),"Increase LODScale.");
618    }
619   
620    {
621        std::ostringstream ostr;
622        ostr<<char(_keyEventDecreaseLODScale);
623        usage.addKeyboardMouseBinding(ostr.str(),"Decrease LODScale.");
624    }
625}
626
627
628bool InteractiveImageHandler::mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const
629{
630    osgUtil::LineSegmentIntersector::Intersections intersections;
631    bool foundIntersection = view==0 ? false :
632        (nv==0 ? view->computeIntersections(ea.getX(), ea.getY(), intersections) :
633                 view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections));
634
635    if (foundIntersection)
636    {
637
638        osg::Vec2 tc(0.5f,0.5f);
639
640        // use the nearest intersection                 
641        const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin());
642        osg::Drawable* drawable = intersection.drawable.get();
643        osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0;
644        osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
645        if (vertices)
646        {
647            // get the vertex indices.
648            const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList;
649            const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList;
650
651            if (indices.size()==3 && ratios.size()==3)
652            {
653                unsigned int i1 = indices[0];
654                unsigned int i2 = indices[1];
655                unsigned int i3 = indices[2];
656
657                float r1 = ratios[0];
658                float r2 = ratios[1];
659                float r3 = ratios[2];
660
661                osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
662                osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
663                if (texcoords_Vec2Array)
664                {
665                    // we have tex coord array so now we can compute the final tex coord at the point of intersection.                               
666                    osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1];
667                    osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2];
668                    osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3];
669                    tc = tc1*r1 + tc2*r2 + tc3*r3;
670                }
671            }
672        }
673
674        osg::TexMat* activeTexMat = 0;
675        osg::Texture* activeTexture = 0;
676       
677        if (geometry->getStateSet())
678        {
679            osg::TexMat* texMat = dynamic_cast<osg::TexMat*>(geometry->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXMAT));
680            if (texMat) activeTexMat = texMat;
681
682            osg::Texture* texture = dynamic_cast<osg::Texture*>(geometry->getStateSet()->getTextureAttribute(0,osg::StateAttribute::TEXTURE));
683            if (texture) activeTexture = texture;
684        }
685
686        if (activeTexMat)
687        {
688            osg::Vec4 tc_transformed = osg::Vec4(tc.x(), tc.y(), 0.0f,0.0f) * activeTexMat->getMatrix();
689            tc.x() = tc_transformed.x();
690            tc.y() = tc_transformed.y();
691        }
692
693        if (dynamic_cast<osg::TextureRectangle*>(activeTexture))
694        {
695            x = int( tc.x() );
696            y = int( tc.y() );
697        }
698        else if (_image.valid())
699        {
700            x = int( float(_image->s()) * tc.x() );
701            y = int( float(_image->t()) * tc.y() );
702        }
703
704
705        return true;
706    }
707   
708    return false;
709}
710
711
712bool InteractiveImageHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
713{
714    if (ea.getHandled()) return false;
715   
716    if (!_image) return false;
717
718    switch(ea.getEventType())
719    {
720        case(osgGA::GUIEventAdapter::MOVE):
721        case(osgGA::GUIEventAdapter::DRAG):
722        case(osgGA::GUIEventAdapter::PUSH):
723        case(osgGA::GUIEventAdapter::RELEASE):
724        {
725            osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
726            int x,y;
727            if (mousePosition(view, nv, ea, x, y))
728            {
729                return _image->sendPointerEvent(x, y, ea.getButtonMask());
730            }
731            break;
732        }
733        case(osgGA::GUIEventAdapter::KEYDOWN):
734        case(osgGA::GUIEventAdapter::KEYUP):
735        {
736            osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
737            int x,y;
738            bool sendKeyEvent = mousePosition(view, nv, ea, x, y);
739       
740            if (sendKeyEvent)
741            {
742                return _image->sendKeyEvent(ea.getKey(), ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN);
743            }         
744        }
745
746        default:
747            return false;
748    }
749    return false;
750}
751
752bool InteractiveImageHandler::cull(osg::NodeVisitor* nv, osg::Drawable*, osg::RenderInfo*) const
753{
754    if (_image.valid())
755    {
756        _image->setFrameLastRendered(nv->getFrameStamp());
757    }
758
759    return false;
760}
761
762}
Note: See TracBrowser for help on using the browser.