root/OpenSceneGraph/trunk/examples/osgscreencapture/osgscreencapture.cpp @ 13361

Revision 12912, 26.6 kB (checked in by robert, 2 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This application is open source and may be redistributed and/or modified   
4 * freely and without restriction, both in commercial and non commercial applications,
5 * as long as this copyright notice is maintained.
6 *
7 * This application is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10*/
11
12#include <osgDB/ReadFile>
13#include <osgDB/WriteFile>
14
15#include <osgUtil/Optimizer>
16#include <osg/CoordinateSystemNode>
17
18#include <osg/Switch>
19#include <osgText/Text>
20
21#include <osgViewer/Viewer>
22#include <osgViewer/ViewerEventHandlers>
23
24#include <osgGA/TrackballManipulator>
25#include <osgGA/FlightManipulator>
26#include <osgGA/DriveManipulator>
27#include <osgGA/KeySwitchMatrixManipulator>
28#include <osgGA/StateSetManipulator>
29#include <osgGA/AnimationPathManipulator>
30#include <osgGA/TerrainManipulator>
31
32#include <iostream>
33#include <sstream>
34#include <string.h>
35
36class WindowCaptureCallback : public osg::Camera::DrawCallback
37{
38    public:
39   
40        enum Mode
41        {
42            READ_PIXELS,
43            SINGLE_PBO,
44            DOUBLE_PBO,
45            TRIPLE_PBO
46        };
47   
48        enum FramePosition
49        {
50            START_FRAME,
51            END_FRAME
52        };
53   
54        struct ContextData : public osg::Referenced
55        {
56       
57            ContextData(osg::GraphicsContext* gc, Mode mode, GLenum readBuffer, const std::string& name):
58                _gc(gc),
59                _mode(mode),
60                _readBuffer(readBuffer),
61                _fileName(name),
62                _pixelFormat(GL_BGRA),
63                _type(GL_UNSIGNED_BYTE),
64                _width(0),
65                _height(0),
66                _currentImageIndex(0),
67                _currentPboIndex(0),
68                _reportTimingFrequency(100),
69                _numTimeValuesRecorded(0),
70                _timeForReadPixels(0.0),
71                _timeForFullCopy(0.0),
72                _timeForMemCpy(0.0)
73
74            {
75                _previousFrameTick = osg::Timer::instance()->tick();
76
77                if (gc->getTraits())
78                {
79                    if (gc->getTraits()->alpha)
80                    {
81                        osg::notify(osg::NOTICE)<<"Select GL_BGRA read back format"<<std::endl;
82                        _pixelFormat = GL_BGRA;
83                    }
84                    else 
85                    {
86                        osg::notify(osg::NOTICE)<<"Select GL_BGR read back format"<<std::endl;
87                        _pixelFormat = GL_BGR;
88                    }
89                }
90           
91                getSize(gc, _width, _height);
92               
93                std::cout<<"Window size "<<_width<<", "<<_height<<std::endl;
94           
95                // single buffered image
96                _imageBuffer.push_back(new osg::Image);
97               
98                // double buffer PBO.
99                switch(_mode)
100                {
101                    case(READ_PIXELS):
102                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with out PixelBufferObject."<<std::endl;
103                        break;
104                    case(SINGLE_PBO):
105                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a single PixelBufferObject."<<std::endl;
106                        _pboBuffer.push_back(0);
107                        break;
108                    case(DOUBLE_PBO):
109                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a double buffer PixelBufferObject."<<std::endl;
110                        _pboBuffer.push_back(0);
111                        _pboBuffer.push_back(0);
112                        break;
113                    case(TRIPLE_PBO):
114                        osg::notify(osg::NOTICE)<<"Reading window usig glReadPixels, with a triple buffer PixelBufferObject."<<std::endl;
115                        _pboBuffer.push_back(0);
116                        _pboBuffer.push_back(0);
117                        _pboBuffer.push_back(0);
118                        break;
119                    default:
120                        break;                               
121                }
122            }
123           
124            void getSize(osg::GraphicsContext* gc, int& width, int& height)
125            {
126                if (gc->getTraits())
127                {
128                    width = gc->getTraits()->width;
129                    height = gc->getTraits()->height;
130                }
131            }
132           
133            void updateTimings(osg::Timer_t tick_start,
134                               osg::Timer_t tick_afterReadPixels,
135                               osg::Timer_t tick_afterMemCpy,
136                               unsigned int dataSize);
137
138            void read()
139            {
140                osg::GLBufferObject::Extensions* ext = osg::GLBufferObject::getExtensions(_gc->getState()->getContextID(),true);
141
142                if (ext->isPBOSupported() && !_pboBuffer.empty())
143                {
144                    if (_pboBuffer.size()==1)
145                    {
146                        singlePBO(ext);
147                    }
148                    else
149                    {
150                        multiPBO(ext);
151                    }
152                }
153                else
154                {
155                    readPixels();
156                }
157            }
158           
159            void readPixels();
160
161            void singlePBO(osg::GLBufferObject::Extensions* ext);
162
163            void multiPBO(osg::GLBufferObject::Extensions* ext);
164       
165            typedef std::vector< osg::ref_ptr<osg::Image> >             ImageBuffer;
166            typedef std::vector< GLuint > PBOBuffer;
167       
168            osg::GraphicsContext*   _gc;
169            Mode                    _mode;
170            GLenum                  _readBuffer;
171            std::string             _fileName;
172           
173            GLenum                  _pixelFormat;
174            GLenum                  _type;
175            int                     _width;
176            int                     _height;
177           
178            unsigned int            _currentImageIndex;
179            ImageBuffer             _imageBuffer;
180           
181            unsigned int            _currentPboIndex;
182            PBOBuffer               _pboBuffer;
183
184            unsigned int            _reportTimingFrequency;
185            unsigned int            _numTimeValuesRecorded;
186            double                  _timeForReadPixels;
187            double                  _timeForFullCopy;
188            double                  _timeForMemCpy;
189            osg::Timer_t            _previousFrameTick;
190        };
191   
192        WindowCaptureCallback(Mode mode, FramePosition position, GLenum readBuffer):
193            _mode(mode),
194            _position(position),
195            _readBuffer(readBuffer)
196        {
197        }
198
199        FramePosition getFramePosition() const { return _position; }
200
201        ContextData* createContextData(osg::GraphicsContext* gc) const
202        {
203            std::stringstream filename;
204            filename << "test_"<<_contextDataMap.size()<<".jpg";
205            return new ContextData(gc, _mode, _readBuffer, filename.str());
206        }
207       
208        ContextData* getContextData(osg::GraphicsContext* gc) const
209        {
210            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
211            osg::ref_ptr<ContextData>& data = _contextDataMap[gc];
212            if (!data) data = createContextData(gc);
213           
214            return data.get();
215        }
216
217        virtual void operator () (osg::RenderInfo& renderInfo) const
218        {
219            glReadBuffer(_readBuffer);
220
221            osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
222            osg::ref_ptr<ContextData> cd = getContextData(gc);
223            cd->read();
224        }
225       
226        typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap;
227
228        Mode                        _mode;       
229        FramePosition               _position;
230        GLenum                      _readBuffer;
231        mutable OpenThreads::Mutex  _mutex;
232        mutable ContextDataMap      _contextDataMap;
233       
234       
235};
236
237void WindowCaptureCallback::ContextData::updateTimings(osg::Timer_t tick_start,
238                                                       osg::Timer_t tick_afterReadPixels,
239                                                       osg::Timer_t tick_afterMemCpy,
240                                                       unsigned int dataSize)
241{
242    if (!_reportTimingFrequency) return;
243
244    double timeForReadPixels = osg::Timer::instance()->delta_s(tick_start, tick_afterReadPixels);
245    double timeForFullCopy = osg::Timer::instance()->delta_s(tick_start, tick_afterMemCpy);
246    double timeForMemCpy = osg::Timer::instance()->delta_s(tick_afterReadPixels, tick_afterMemCpy);
247
248    _timeForReadPixels += timeForReadPixels;
249    _timeForFullCopy += timeForFullCopy;
250    _timeForMemCpy += timeForMemCpy;
251   
252    ++_numTimeValuesRecorded;
253   
254    if (_numTimeValuesRecorded==_reportTimingFrequency)
255    {
256        timeForReadPixels = _timeForReadPixels/double(_numTimeValuesRecorded);
257        timeForFullCopy = _timeForFullCopy/double(_numTimeValuesRecorded);
258        timeForMemCpy = _timeForMemCpy/double(_numTimeValuesRecorded);
259       
260        double averageFrameTime =  osg::Timer::instance()->delta_s(_previousFrameTick, tick_afterMemCpy)/double(_numTimeValuesRecorded);
261        double fps = 1.0/averageFrameTime;   
262        _previousFrameTick = tick_afterMemCpy;
263
264        _timeForReadPixels = 0.0;
265        _timeForFullCopy = 0.0;
266        _timeForMemCpy = 0.0;
267
268        _numTimeValuesRecorded = 0;
269
270        double numMPixels = double(_width * _height) / 1000000.0;
271        double numMb = double(dataSize) / (1024*1024);
272
273        int prec = osg::notify(osg::NOTICE).precision(5);
274
275        if (timeForMemCpy==0.0)
276        {
277            osg::notify(osg::NOTICE)<<"fps = "<<fps<<", full frame copy = "<<timeForFullCopy*1000.0f<<"ms rate = "<<numMPixels / timeForFullCopy<<" Mpixel/sec, copy speed = "<<numMb / timeForFullCopy<<" Mb/sec"<<std::endl;
278        }
279        else
280        {
281            osg::notify(osg::NOTICE)<<"fps = "<<fps<<", full frame copy = "<<timeForFullCopy*1000.0f<<"ms rate = "<<numMPixels / timeForFullCopy<<" Mpixel/sec, "<<numMb / timeForFullCopy<< " Mb/sec "<<
282                                      "time for memcpy = "<<timeForMemCpy*1000.0<<"ms  memcpy speed = "<<numMb / timeForMemCpy<<" Mb/sec"<<std::endl;
283        }
284        osg::notify(osg::NOTICE).precision(prec);
285
286    }
287
288}
289
290void WindowCaptureCallback::ContextData::readPixels()
291{
292    // std::cout<<"readPixels("<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
293
294    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
295    unsigned int nextPboIndex = _pboBuffer.empty() ? 0 : (_currentPboIndex+1)%_pboBuffer.size();
296
297    int width=0, height=0;
298    getSize(_gc, width, height);
299    if (width!=_width || _height!=height)
300    {
301        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
302        _width = width;
303        _height = height;
304    }
305
306    osg::Image* image = _imageBuffer[_currentImageIndex].get();
307
308    osg::Timer_t tick_start = osg::Timer::instance()->tick();
309
310#if 1
311    image->readPixels(0,0,_width,_height,
312                      _pixelFormat,_type);
313#endif
314
315    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
316
317    updateTimings(tick_start, tick_afterReadPixels, tick_afterReadPixels, image->getTotalSizeInBytes());
318
319    if (!_fileName.empty())
320    {
321        // osgDB::writeImageFile(*image, _fileName);
322    }
323
324    _currentImageIndex = nextImageIndex;
325    _currentPboIndex = nextPboIndex;
326}
327
328void WindowCaptureCallback::ContextData::singlePBO(osg::GLBufferObject::Extensions* ext)
329{
330    // std::cout<<"singelPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
331
332    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
333
334    int width=0, height=0;
335    getSize(_gc, width, height);
336    if (width!=_width || _height!=height)
337    {
338        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
339        _width = width;
340        _height = height;
341    }
342
343    GLuint& pbo = _pboBuffer[0];
344   
345    osg::Image* image = _imageBuffer[_currentImageIndex].get();
346    if (image->s() != _width ||
347        image->t() != _height)
348    {
349        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
350        image->allocateImage(_width, _height, 1, _pixelFormat, _type);
351       
352        if (pbo!=0)
353        {
354            osg::notify(osg::NOTICE)<<"deleting pbo "<<pbo<<std::endl;
355            ext->glDeleteBuffers (1, &pbo);
356            pbo = 0;
357        }
358    }
359   
360   
361    if (pbo==0)
362    {
363        ext->glGenBuffers(1, &pbo);
364        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
365        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
366
367        osg::notify(osg::NOTICE)<<"Generating pbo "<<pbo<<std::endl;
368    }
369    else
370    {
371        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
372    }
373
374    osg::Timer_t tick_start = osg::Timer::instance()->tick();
375
376#if 1
377    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);
378#endif
379
380    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
381
382    GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
383                                              GL_READ_ONLY_ARB);
384    if(src)
385    {
386        memcpy(image->data(), src, image->getTotalSizeInBytes());
387       
388        ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
389    }
390
391    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
392
393    osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick();
394
395    updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes());
396
397    if (!_fileName.empty())
398    {
399        // osgDB::writeImageFile(*image, _fileName);
400    }
401
402
403    _currentImageIndex = nextImageIndex;
404}
405
406void WindowCaptureCallback::ContextData::multiPBO(osg::GLBufferObject::Extensions* ext)
407{
408    // std::cout<<"multiPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
409    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
410    unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
411
412    int width=0, height=0;
413    getSize(_gc, width, height);
414    if (width!=_width || _height!=height)
415    {
416        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
417        _width = width;
418        _height = height;
419    }
420
421    GLuint& copy_pbo = _pboBuffer[_currentPboIndex];
422    GLuint& read_pbo = _pboBuffer[nextPboIndex];
423   
424    osg::Image* image = _imageBuffer[_currentImageIndex].get();
425    if (image->s() != _width ||
426        image->t() != _height)
427    {
428        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
429        image->allocateImage(_width, _height, 1, _pixelFormat, _type);
430       
431        if (read_pbo!=0)
432        {
433            osg::notify(osg::NOTICE)<<"deleting pbo "<<read_pbo<<std::endl;
434            ext->glDeleteBuffers (1, &read_pbo);
435            read_pbo = 0;
436        }
437
438        if (copy_pbo!=0)
439        {
440            osg::notify(osg::NOTICE)<<"deleting pbo "<<copy_pbo<<std::endl;
441            ext->glDeleteBuffers (1, &copy_pbo);
442            copy_pbo = 0;
443        }
444    }
445   
446   
447    bool doCopy = copy_pbo!=0;
448    if (copy_pbo==0)
449    {
450        ext->glGenBuffers(1, &copy_pbo);
451        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo);
452        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
453
454        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl;
455    }
456
457    if (read_pbo==0)
458    {
459        ext->glGenBuffers(1, &read_pbo);
460        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo);
461        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
462
463        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl;
464    }
465    else
466    {
467        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo);
468    }
469
470    osg::Timer_t tick_start = osg::Timer::instance()->tick();
471
472#if 1
473    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);
474#endif
475
476    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
477
478    if (doCopy)
479    {
480
481        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo);
482
483        GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
484                                                  GL_READ_ONLY_ARB);
485        if(src)
486        {
487            memcpy(image->data(), src, image->getTotalSizeInBytes());
488            ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
489        }
490
491        if (!_fileName.empty())
492        {
493            // osgDB::writeImageFile(*image, _fileName);
494        }
495    }
496   
497    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
498
499    osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick();
500   
501    updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes());
502
503    _currentImageIndex = nextImageIndex;
504    _currentPboIndex = nextPboIndex;
505}
506
507void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback)
508{
509   
510    if (callback->getFramePosition()==WindowCaptureCallback::START_FRAME)
511    {
512        osgViewer::ViewerBase::Windows windows;
513        viewer.getWindows(windows);
514        for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
515            itr != windows.end();
516            ++itr)
517        {
518            osgViewer::GraphicsWindow* window = *itr;
519            osg::GraphicsContext::Cameras& cameras = window->getCameras();
520            osg::Camera* firstCamera = 0;
521            for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
522                cam_itr != cameras.end();
523                ++cam_itr)
524            {
525                if (firstCamera)
526                {
527                    if ((*cam_itr)->getRenderOrder() < firstCamera->getRenderOrder())
528                    {
529                        firstCamera = (*cam_itr);
530                    }
531                    if ((*cam_itr)->getRenderOrder() == firstCamera->getRenderOrder() &&
532                        (*cam_itr)->getRenderOrderNum() < firstCamera->getRenderOrderNum())
533                    {
534                        firstCamera = (*cam_itr);
535                    }
536                }
537                else
538                {
539                    firstCamera = *cam_itr;
540                }
541            }
542
543            if (firstCamera)
544            {
545                osg::notify(osg::NOTICE)<<"First camera "<<firstCamera<<std::endl;
546
547                firstCamera->setInitialDrawCallback(callback);
548            }
549            else
550            {
551                osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
552            }
553        }
554    }
555    else
556    {   
557        osgViewer::ViewerBase::Windows windows;
558        viewer.getWindows(windows);
559        for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
560            itr != windows.end();
561            ++itr)
562        {
563            osgViewer::GraphicsWindow* window = *itr;
564            osg::GraphicsContext::Cameras& cameras = window->getCameras();
565            osg::Camera* lastCamera = 0;
566            for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
567                cam_itr != cameras.end();
568                ++cam_itr)
569            {
570                if (lastCamera)
571                {
572                    if ((*cam_itr)->getRenderOrder() > lastCamera->getRenderOrder())
573                    {
574                        lastCamera = (*cam_itr);
575                    }
576                    if ((*cam_itr)->getRenderOrder() == lastCamera->getRenderOrder() &&
577                        (*cam_itr)->getRenderOrderNum() >= lastCamera->getRenderOrderNum())
578                    {
579                        lastCamera = (*cam_itr);
580                    }
581                }
582                else
583                {
584                    lastCamera = *cam_itr;
585                }
586            }
587
588            if (lastCamera)
589            {
590                osg::notify(osg::NOTICE)<<"Last camera "<<lastCamera<<std::endl;
591
592                lastCamera->setFinalDrawCallback(callback);
593            }
594            else
595            {
596                osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
597            }
598        }
599    }
600}
601
602int main(int argc, char** argv)
603{
604    // use an ArgumentParser object to manage the program arguments.
605    osg::ArgumentParser arguments(&argc,argv);
606
607    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
608    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
609
610    osgViewer::Viewer viewer(arguments);
611
612    unsigned int helpType = 0;
613    if ((helpType = arguments.readHelpType()))
614    {
615        arguments.getApplicationUsage()->write(std::cout, helpType);
616        return 1;
617    }
618   
619    // report any errors if they have occurred when parsing the program arguments.
620    if (arguments.errors())
621    {
622        arguments.writeErrorMessages(std::cout);
623        return 1;
624    }
625   
626    if (arguments.argc()<=1)
627    {
628        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
629        return 1;
630    }
631
632    // set up the camera manipulators.
633    {
634        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
635
636        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
637        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
638        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
639        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
640
641        std::string pathfile;
642        char keyForAnimationPath = '5';
643        while (arguments.read("-p",pathfile))
644        {
645            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
646            if (apm || !apm->valid())
647            {
648                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
649                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
650                keyswitchManipulator->selectMatrixManipulator(num);
651                ++keyForAnimationPath;
652            }
653        }
654
655        viewer.setCameraManipulator( keyswitchManipulator.get() );
656    }
657
658    // add the state manipulator
659    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
660   
661    // add the thread model handler
662    viewer.addEventHandler(new osgViewer::ThreadingHandler);
663
664    // add the window size toggle handler
665    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
666       
667    // add the stats handler
668    viewer.addEventHandler(new osgViewer::StatsHandler);
669
670    // add the help handler
671    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
672
673    // add the record camera path handler
674    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
675
676    // add the LOD Scale handler
677    viewer.addEventHandler(new osgViewer::LODScaleHandler);
678
679    GLenum readBuffer = GL_BACK;
680    WindowCaptureCallback::FramePosition position = WindowCaptureCallback::END_FRAME;
681    WindowCaptureCallback::Mode mode = WindowCaptureCallback::DOUBLE_PBO;
682
683    while (arguments.read("--start-frame")) { position = WindowCaptureCallback::START_FRAME; readBuffer = GL_FRONT; }
684    while (arguments.read("--end-frame")) position = WindowCaptureCallback::END_FRAME;
685
686    while (arguments.read("--front")) readBuffer = GL_FRONT;
687    while (arguments.read("--back")) readBuffer = GL_BACK;
688
689    while (arguments.read("--no-pbo")) mode = WindowCaptureCallback::READ_PIXELS;
690    while (arguments.read("--single-pbo")) mode = WindowCaptureCallback::SINGLE_PBO;
691    while (arguments.read("--double-pbo")) mode = WindowCaptureCallback::DOUBLE_PBO;
692    while (arguments.read("--triple-pbo")) mode = WindowCaptureCallback::TRIPLE_PBO;
693
694   
695    unsigned int width=1280;
696    unsigned int height=1024;
697    bool pbufferOnly = false;
698    osg::ref_ptr<osg::GraphicsContext> pbuffer;
699    if (arguments.read("--pbuffer",width,height) ||
700        (pbufferOnly = arguments.read("--pbuffer-only",width,height)))
701    {
702        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
703        traits->x = 0;
704        traits->y = 0;
705        traits->width = width;
706        traits->height = height;
707        traits->red = 8;
708        traits->green = 8;
709        traits->blue = 8;
710        traits->alpha = 8;
711        traits->windowDecoration = false;
712        traits->pbuffer = true;
713        traits->doubleBuffer = true;
714        traits->sharedContext = 0;
715
716        pbuffer = osg::GraphicsContext::createGraphicsContext(traits.get());
717        if (pbuffer.valid())
718        {
719            osg::notify(osg::NOTICE)<<"Pixel buffer has been created successfully."<<std::endl;
720        }
721        else
722        {
723            osg::notify(osg::NOTICE)<<"Pixel buffer has not been created successfully."<<std::endl;
724        }
725
726    }
727       
728    // load the data
729    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
730    if (!loadedModel)
731    {
732        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
733        return 1;
734    }
735
736    // any option left unread are converted into errors to write out later.
737    arguments.reportRemainingOptionsAsUnrecognized();
738
739    // report any errors if they have occurred when parsing the program arguments.
740    if (arguments.errors())
741    {
742        arguments.writeErrorMessages(std::cout);
743        return 1;
744    }
745
746
747    // optimize the scene graph, remove redundant nodes and state etc.
748    osgUtil::Optimizer optimizer;
749    optimizer.optimize(loadedModel.get());
750
751    viewer.setSceneData( loadedModel.get() );
752
753   
754    if (pbuffer.valid())
755    {
756        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
757        camera->setGraphicsContext(pbuffer.get());
758        camera->setViewport(new osg::Viewport(0,0,width,height));
759        GLenum buffer = pbuffer->getTraits()->doubleBuffer ? GL_BACK : GL_FRONT;
760        camera->setDrawBuffer(buffer);
761        camera->setReadBuffer(buffer);
762        camera->setFinalDrawCallback(new WindowCaptureCallback(mode, position, readBuffer));
763
764        if (pbufferOnly)
765        {
766            viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
767
768            viewer.realize();
769        }
770        else
771        {
772            viewer.realize();
773
774            viewer.stopThreading();
775
776            pbuffer->realize();
777
778            viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
779
780            viewer.startThreading();
781        }
782    }
783    else
784    {
785        viewer.realize();
786
787        addCallbackToViewer(viewer, new WindowCaptureCallback(mode, position, readBuffer));
788    }
789
790    return viewer.run();
791
792}
Note: See TracBrowser for help on using the browser.