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

Revision 8345, 26.1 kB (checked in by robert, 7 years ago)

Added basic --pbuffer width height support

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    _previousFrameTick = tick_afterMemCpy;
252   
253    ++_numTimeValuesRecorded;
254   
255    if (_numTimeValuesRecorded==_reportTimingFrequency)
256    {
257        timeForReadPixels = _timeForReadPixels/double(_numTimeValuesRecorded);
258        timeForFullCopy = _timeForFullCopy/double(_numTimeValuesRecorded);
259        timeForMemCpy = _timeForMemCpy/double(_numTimeValuesRecorded);
260   
261        _timeForReadPixels = 0.0;
262        _timeForFullCopy = 0.0;
263        _timeForMemCpy = 0.0;
264
265        _numTimeValuesRecorded = 0;
266
267        double numMPixels = double(_width * _height) / 1000000.0;
268        double numMb = double(dataSize) / (1024*1024);
269
270        if (timeForMemCpy==0.0)
271        {
272            osg::notify(osg::NOTICE)<<"Full frame copy = "<<timeForFullCopy*1000.0f<<"ms rate = "<<numMPixels / timeForFullCopy<<" Mpixel/sec, copy speed = "<<numMb / timeForFullCopy<<" Mb/sec"<<std::endl;
273        }
274        else
275        {
276            osg::notify(osg::NOTICE)<<"Full frame copy = "<<timeForFullCopy*1000.0f<<"ms rate = "<<numMPixels / timeForFullCopy<<" Mpixel/sec, "<<numMb / timeForFullCopy<< " Mb/sec "<<
277                                      "time for memcpy = "<<timeForMemCpy*1000.0<<"ms  memcpy speed = "<<numMb / timeForMemCpy<<" Mb/sec"<<std::endl;
278        }
279
280    }
281
282}
283
284void WindowCaptureCallback::ContextData::readPixels()
285{
286    // std::cout<<"readPixels("<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
287
288    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
289    unsigned int nextPboIndex = _pboBuffer.empty() ? 0 : (_currentPboIndex+1)%_pboBuffer.size();
290
291    int width=0, height=0;
292    getSize(_gc, width, height);
293    if (width!=_width || _height!=height)
294    {
295        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
296        _width = width;
297        _height = height;
298    }
299
300    osg::Image* image = _imageBuffer[_currentImageIndex].get();
301
302    osg::Timer_t tick_start = osg::Timer::instance()->tick();
303
304#if 1
305    image->readPixels(0,0,_width,_height,
306                      _pixelFormat,_type);
307#endif
308
309    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
310
311    updateTimings(tick_start, tick_afterReadPixels, tick_afterReadPixels, image->getTotalSizeInBytes());
312
313    if (!_fileName.empty())
314    {
315        // osgDB::writeImageFile(*image, _fileName);
316    }
317
318    _currentImageIndex = nextImageIndex;
319    _currentPboIndex = nextPboIndex;
320}
321
322void WindowCaptureCallback::ContextData::singlePBO(osg::BufferObject::Extensions* ext)
323{
324    // std::cout<<"singelPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
325
326    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
327
328    int width=0, height=0;
329    getSize(_gc, width, height);
330    if (width!=_width || _height!=height)
331    {
332        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
333        _width = width;
334        _height = height;
335    }
336
337    GLuint& pbo = _pboBuffer[0];
338   
339    osg::Image* image = _imageBuffer[_currentImageIndex].get();
340    if (image->s() != _width ||
341        image->t() != _height)
342    {
343        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
344        image->allocateImage(_width, _height, 1, _pixelFormat, _type);
345       
346        if (pbo!=0)
347        {
348            osg::notify(osg::NOTICE)<<"deleting pbo "<<pbo<<std::endl;
349            ext->glDeleteBuffers (1, &pbo);
350            pbo = 0;
351        }
352    }
353   
354   
355    if (pbo==0)
356    {
357        ext->glGenBuffers(1, &pbo);
358        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
359        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
360
361        osg::notify(osg::NOTICE)<<"Generating pbo "<<pbo<<std::endl;
362    }
363    else
364    {
365        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
366    }
367
368    osg::Timer_t tick_start = osg::Timer::instance()->tick();
369
370#if 1
371    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);
372#endif
373
374    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
375
376    GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
377                                              GL_READ_ONLY_ARB);
378    if(src)
379    {
380        memcpy(image->data(), src, image->getTotalSizeInBytes());
381        ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
382    }
383
384    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
385
386    osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick();
387
388    updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes());
389
390    if (!_fileName.empty())
391    {
392        // osgDB::writeImageFile(*image, _fileName);
393    }
394
395
396    _currentImageIndex = nextImageIndex;
397}
398
399void WindowCaptureCallback::ContextData::multiPBO(osg::BufferObject::Extensions* ext)
400{
401    // std::cout<<"multiPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
402    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
403    unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
404
405    int width=0, height=0;
406    getSize(_gc, width, height);
407    if (width!=_width || _height!=height)
408    {
409        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
410        _width = width;
411        _height = height;
412    }
413
414    GLuint& copy_pbo = _pboBuffer[_currentPboIndex];
415    GLuint& read_pbo = _pboBuffer[nextPboIndex];
416   
417    osg::Image* image = _imageBuffer[_currentImageIndex].get();
418    if (image->s() != _width ||
419        image->t() != _height)
420    {
421        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
422        image->allocateImage(_width, _height, 1, _pixelFormat, _type);
423       
424        if (read_pbo!=0)
425        {
426            osg::notify(osg::NOTICE)<<"deleting pbo "<<read_pbo<<std::endl;
427            ext->glDeleteBuffers (1, &read_pbo);
428            read_pbo = 0;
429        }
430
431        if (copy_pbo!=0)
432        {
433            osg::notify(osg::NOTICE)<<"deleting pbo "<<copy_pbo<<std::endl;
434            ext->glDeleteBuffers (1, &copy_pbo);
435            copy_pbo = 0;
436        }
437    }
438   
439   
440    bool doCopy = copy_pbo!=0;
441    if (copy_pbo==0)
442    {
443        ext->glGenBuffers(1, &copy_pbo);
444        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo);
445        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
446
447        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl;
448    }
449
450    if (read_pbo==0)
451    {
452        ext->glGenBuffers(1, &read_pbo);
453        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo);
454        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
455
456        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl;
457    }
458    else
459    {
460        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo);
461    }
462
463    osg::Timer_t tick_start = osg::Timer::instance()->tick();
464
465#if 1
466    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);
467#endif
468
469    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
470
471    if (doCopy)
472    {
473
474        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo);
475
476        GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
477                                                  GL_READ_ONLY_ARB);
478        if(src)
479        {
480            memcpy(image->data(), src, image->getTotalSizeInBytes());
481            ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
482        }
483
484        if (!_fileName.empty())
485        {
486            // osgDB::writeImageFile(*image, _fileName);
487        }
488    }
489   
490    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
491
492    osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick();
493   
494    updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes());
495
496    _currentImageIndex = nextImageIndex;
497    _currentPboIndex = nextPboIndex;
498}
499
500void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback)
501{
502   
503    if (callback->getFramePosition()==WindowCaptureCallback::START_FRAME)
504    {
505        osgViewer::ViewerBase::Windows windows;
506        viewer.getWindows(windows);
507        for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
508            itr != windows.end();
509            ++itr)
510        {
511            osgViewer::GraphicsWindow* window = *itr;
512            osg::GraphicsContext::Cameras& cameras = window->getCameras();
513            osg::Camera* firstCamera = 0;
514            for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
515                cam_itr != cameras.end();
516                ++cam_itr)
517            {
518                if (firstCamera)
519                {
520                    if ((*cam_itr)->getRenderOrder() < firstCamera->getRenderOrder())
521                    {
522                        firstCamera = (*cam_itr);
523                    }
524                    if ((*cam_itr)->getRenderOrder() == firstCamera->getRenderOrder() &&
525                        (*cam_itr)->getRenderOrderNum() < firstCamera->getRenderOrderNum())
526                    {
527                        firstCamera = (*cam_itr);
528                    }
529                }
530                else
531                {
532                    firstCamera = *cam_itr;
533                }
534            }
535
536            if (firstCamera)
537            {
538                osg::notify(osg::NOTICE)<<"First camera "<<firstCamera<<std::endl;
539
540                firstCamera->setInitialDrawCallback(callback);
541            }
542            else
543            {
544                osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
545            }
546        }
547    }
548    else
549    {   
550        osgViewer::ViewerBase::Windows windows;
551        viewer.getWindows(windows);
552        for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
553            itr != windows.end();
554            ++itr)
555        {
556            osgViewer::GraphicsWindow* window = *itr;
557            osg::GraphicsContext::Cameras& cameras = window->getCameras();
558            osg::Camera* lastCamera = 0;
559            for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
560                cam_itr != cameras.end();
561                ++cam_itr)
562            {
563                if (lastCamera)
564                {
565                    if ((*cam_itr)->getRenderOrder() > lastCamera->getRenderOrder())
566                    {
567                        lastCamera = (*cam_itr);
568                    }
569                    if ((*cam_itr)->getRenderOrder() == lastCamera->getRenderOrder() &&
570                        (*cam_itr)->getRenderOrderNum() >= lastCamera->getRenderOrderNum())
571                    {
572                        lastCamera = (*cam_itr);
573                    }
574                }
575                else
576                {
577                    lastCamera = *cam_itr;
578                }
579            }
580
581            if (lastCamera)
582            {
583                osg::notify(osg::NOTICE)<<"Last camera "<<lastCamera<<std::endl;
584
585                lastCamera->setFinalDrawCallback(callback);
586            }
587            else
588            {
589                osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
590            }
591        }
592    }
593}
594
595int main(int argc, char** argv)
596{
597    // use an ArgumentParser object to manage the program arguments.
598    osg::ArgumentParser arguments(&argc,argv);
599
600    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
601    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
602    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
603
604    osgViewer::Viewer viewer(arguments);
605
606    unsigned int helpType = 0;
607    if ((helpType = arguments.readHelpType()))
608    {
609        arguments.getApplicationUsage()->write(std::cout, helpType);
610        return 1;
611    }
612   
613    // report any errors if they have occurred when parsing the program arguments.
614    if (arguments.errors())
615    {
616        arguments.writeErrorMessages(std::cout);
617        return 1;
618    }
619   
620    if (arguments.argc()<=1)
621    {
622        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
623        return 1;
624    }
625
626    // set up the camera manipulators.
627    {
628        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
629
630        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
631        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
632        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
633        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
634
635        std::string pathfile;
636        char keyForAnimationPath = '5';
637        while (arguments.read("-p",pathfile))
638        {
639            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
640            if (apm || !apm->valid())
641            {
642                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
643                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
644                keyswitchManipulator->selectMatrixManipulator(num);
645                ++keyForAnimationPath;
646            }
647        }
648
649        viewer.setCameraManipulator( keyswitchManipulator.get() );
650    }
651
652    // add the state manipulator
653    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
654   
655    // add the thread model handler
656    viewer.addEventHandler(new osgViewer::ThreadingHandler);
657
658    // add the window size toggle handler
659    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
660       
661    // add the stats handler
662    viewer.addEventHandler(new osgViewer::StatsHandler);
663
664    // add the help handler
665    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
666
667    // add the record camera path handler
668    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
669
670    // add the LOD Scale handler
671    viewer.addEventHandler(new osgViewer::LODScaleHandler);
672
673    GLenum readBuffer = GL_BACK;
674    WindowCaptureCallback::FramePosition position = WindowCaptureCallback::END_FRAME;
675    WindowCaptureCallback::Mode mode = WindowCaptureCallback::DOUBLE_PBO;
676
677    while (arguments.read("--start-frame")) { position = WindowCaptureCallback::START_FRAME; readBuffer = GL_FRONT; }
678    while (arguments.read("--end-frame")) position = WindowCaptureCallback::END_FRAME;
679
680    while (arguments.read("--front")) readBuffer = GL_FRONT;
681    while (arguments.read("--back")) readBuffer = GL_BACK;
682
683    while (arguments.read("--no-pbo")) mode = WindowCaptureCallback::READ_PIXELS;
684    while (arguments.read("--single-pbo")) mode = WindowCaptureCallback::SINGLE_PBO;
685    while (arguments.read("--double-pbo")) mode = WindowCaptureCallback::DOUBLE_PBO;
686    while (arguments.read("--triple-pbo")) mode = WindowCaptureCallback::TRIPLE_PBO;
687
688   
689    unsigned int width=1280;
690    unsigned int height=1024;
691    osg::ref_ptr<osg::GraphicsContext> pbuffer;
692    if (arguments.read("--pbuffer",width,height))
693    {
694        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
695        traits->x = 0;
696        traits->y = 0;
697        traits->width = width;
698        traits->height = height;
699        traits->red = 8;
700        traits->green = 8;
701        traits->blue = 8;
702        traits->alpha = 8;
703        traits->windowDecoration = false;
704        traits->pbuffer = true;
705        traits->doubleBuffer = true;
706        traits->sharedContext = 0;
707
708        pbuffer = osg::GraphicsContext::createGraphicsContext(traits.get());
709        if (pbuffer.valid())
710        {
711            osg::notify(osg::NOTICE)<<"Pixel buffer has been created successfully."<<std::endl;
712        }
713        else
714        {
715            osg::notify(osg::NOTICE)<<"Pixel buffer has not been created successfully."<<std::endl;
716        }
717
718    }
719       
720    // load the data
721    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
722    if (!loadedModel)
723    {
724        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
725        return 1;
726    }
727
728    // any option left unread are converted into errors to write out later.
729    arguments.reportRemainingOptionsAsUnrecognized();
730
731    // report any errors if they have occurred when parsing the program arguments.
732    if (arguments.errors())
733    {
734        arguments.writeErrorMessages(std::cout);
735        return 1;
736    }
737
738
739    // optimize the scene graph, remove redundant nodes and state etc.
740    osgUtil::Optimizer optimizer;
741    optimizer.optimize(loadedModel.get());
742
743    viewer.setSceneData( loadedModel.get() );
744
745    viewer.realize();
746   
747    if (pbuffer.valid())
748    {
749        viewer.stopThreading();
750       
751        pbuffer->realize();
752   
753        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
754        camera->setGraphicsContext(pbuffer.get());
755        camera->setViewport(new osg::Viewport(0,0,width,height));
756        GLenum buffer = pbuffer->getTraits()->doubleBuffer ? GL_BACK : GL_FRONT;
757        camera->setDrawBuffer(buffer);
758        camera->setReadBuffer(buffer);
759        camera->setFinalDrawCallback(new WindowCaptureCallback(mode, position, readBuffer));
760
761        viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
762       
763        viewer.startThreading();
764    }
765    else
766    {
767        addCallbackToViewer(viewer, new WindowCaptureCallback(mode, position, readBuffer));
768    }
769
770    return viewer.run();
771
772}
Note: See TracBrowser for help on using the browser.