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

Revision 11931, 26.6 kB (checked in by robert, 3 years ago)

Fixed typo of commercial

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        ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
388    }
389
390    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
391
392    osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick();
393
394    updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes());
395
396    if (!_fileName.empty())
397    {
398        // osgDB::writeImageFile(*image, _fileName);
399    }
400
401
402    _currentImageIndex = nextImageIndex;
403}
404
405void WindowCaptureCallback::ContextData::multiPBO(osg::GLBufferObject::Extensions* ext)
406{
407    // std::cout<<"multiPBO(  "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
408    unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
409    unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
410
411    int width=0, height=0;
412    getSize(_gc, width, height);
413    if (width!=_width || _height!=height)
414    {
415        std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
416        _width = width;
417        _height = height;
418    }
419
420    GLuint& copy_pbo = _pboBuffer[_currentPboIndex];
421    GLuint& read_pbo = _pboBuffer[nextPboIndex];
422   
423    osg::Image* image = _imageBuffer[_currentImageIndex].get();
424    if (image->s() != _width ||
425        image->t() != _height)
426    {
427        osg::notify(osg::NOTICE)<<"Allocating image "<<std::endl;
428        image->allocateImage(_width, _height, 1, _pixelFormat, _type);
429       
430        if (read_pbo!=0)
431        {
432            osg::notify(osg::NOTICE)<<"deleting pbo "<<read_pbo<<std::endl;
433            ext->glDeleteBuffers (1, &read_pbo);
434            read_pbo = 0;
435        }
436
437        if (copy_pbo!=0)
438        {
439            osg::notify(osg::NOTICE)<<"deleting pbo "<<copy_pbo<<std::endl;
440            ext->glDeleteBuffers (1, &copy_pbo);
441            copy_pbo = 0;
442        }
443    }
444   
445   
446    bool doCopy = copy_pbo!=0;
447    if (copy_pbo==0)
448    {
449        ext->glGenBuffers(1, &copy_pbo);
450        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo);
451        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
452
453        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl;
454    }
455
456    if (read_pbo==0)
457    {
458        ext->glGenBuffers(1, &read_pbo);
459        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo);
460        ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, image->getTotalSizeInBytes(), 0, GL_STREAM_READ);
461
462        osg::notify(osg::NOTICE)<<"Generating pbo "<<read_pbo<<std::endl;
463    }
464    else
465    {
466        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, read_pbo);
467    }
468
469    osg::Timer_t tick_start = osg::Timer::instance()->tick();
470
471#if 1
472    glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);
473#endif
474
475    osg::Timer_t tick_afterReadPixels = osg::Timer::instance()->tick();
476
477    if (doCopy)
478    {
479
480        ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, copy_pbo);
481
482        GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
483                                                  GL_READ_ONLY_ARB);
484        if(src)
485        {
486            memcpy(image->data(), src, image->getTotalSizeInBytes());
487            ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
488        }
489
490        if (!_fileName.empty())
491        {
492            // osgDB::writeImageFile(*image, _fileName);
493        }
494    }
495   
496    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
497
498    osg::Timer_t tick_afterMemCpy = osg::Timer::instance()->tick();
499   
500    updateTimings(tick_start, tick_afterReadPixels, tick_afterMemCpy, image->getTotalSizeInBytes());
501
502    _currentImageIndex = nextImageIndex;
503    _currentPboIndex = nextPboIndex;
504}
505
506void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback)
507{
508   
509    if (callback->getFramePosition()==WindowCaptureCallback::START_FRAME)
510    {
511        osgViewer::ViewerBase::Windows windows;
512        viewer.getWindows(windows);
513        for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
514            itr != windows.end();
515            ++itr)
516        {
517            osgViewer::GraphicsWindow* window = *itr;
518            osg::GraphicsContext::Cameras& cameras = window->getCameras();
519            osg::Camera* firstCamera = 0;
520            for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
521                cam_itr != cameras.end();
522                ++cam_itr)
523            {
524                if (firstCamera)
525                {
526                    if ((*cam_itr)->getRenderOrder() < firstCamera->getRenderOrder())
527                    {
528                        firstCamera = (*cam_itr);
529                    }
530                    if ((*cam_itr)->getRenderOrder() == firstCamera->getRenderOrder() &&
531                        (*cam_itr)->getRenderOrderNum() < firstCamera->getRenderOrderNum())
532                    {
533                        firstCamera = (*cam_itr);
534                    }
535                }
536                else
537                {
538                    firstCamera = *cam_itr;
539                }
540            }
541
542            if (firstCamera)
543            {
544                osg::notify(osg::NOTICE)<<"First camera "<<firstCamera<<std::endl;
545
546                firstCamera->setInitialDrawCallback(callback);
547            }
548            else
549            {
550                osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
551            }
552        }
553    }
554    else
555    {   
556        osgViewer::ViewerBase::Windows windows;
557        viewer.getWindows(windows);
558        for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
559            itr != windows.end();
560            ++itr)
561        {
562            osgViewer::GraphicsWindow* window = *itr;
563            osg::GraphicsContext::Cameras& cameras = window->getCameras();
564            osg::Camera* lastCamera = 0;
565            for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
566                cam_itr != cameras.end();
567                ++cam_itr)
568            {
569                if (lastCamera)
570                {
571                    if ((*cam_itr)->getRenderOrder() > lastCamera->getRenderOrder())
572                    {
573                        lastCamera = (*cam_itr);
574                    }
575                    if ((*cam_itr)->getRenderOrder() == lastCamera->getRenderOrder() &&
576                        (*cam_itr)->getRenderOrderNum() >= lastCamera->getRenderOrderNum())
577                    {
578                        lastCamera = (*cam_itr);
579                    }
580                }
581                else
582                {
583                    lastCamera = *cam_itr;
584                }
585            }
586
587            if (lastCamera)
588            {
589                osg::notify(osg::NOTICE)<<"Last camera "<<lastCamera<<std::endl;
590
591                lastCamera->setFinalDrawCallback(callback);
592            }
593            else
594            {
595                osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
596            }
597        }
598    }
599}
600
601int main(int argc, char** argv)
602{
603    // use an ArgumentParser object to manage the program arguments.
604    osg::ArgumentParser arguments(&argc,argv);
605
606    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
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.