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

Revision 8346, 26.7 kB (checked in by robert, 6 years ago)

Introduce --pbuffer-only width height option, and added fps reporting to stats output

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