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

Revision 8332, 10.9 kB (checked in by robert, 7 years ago)

Added basic glReadPixels code

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        struct ContextData : public osg::Referenced
40        {
41       
42            ContextData(osg::GraphicsContext* gc, const std::string& name):
43                _gc(gc),
44                _fileName(name),
45                _pixelFormat(GL_RGB),
46                _type(GL_UNSIGNED_BYTE),
47                _width(0),
48                _height(0),
49                _currentImageIndex(0),
50                _currentPboIndex(0)
51            {
52                getSize(gc, _width, _height);
53               
54                std::cout<<"Window size "<<_width<<", "<<_height<<std::endl;
55           
56                // single buffered image
57                _imageBuffer.push_back(new osg::Image);
58               
59                // double buffer PBO.
60                _pboBuffer.push_back(new osg::PixelBufferObject);
61                _pboBuffer.push_back(new osg::PixelBufferObject);
62            }
63           
64            void getSize(osg::GraphicsContext* gc, int& width, int& height)
65            {
66                if (gc->getTraits())
67                {
68                    width = gc->getTraits()->width;
69                    height = gc->getTraits()->height;
70                }
71            }
72           
73            void read()
74            {
75                std::cout<<"Read to "<<_fileName<<" image "<<_currentImageIndex<<" "<<_currentPboIndex<<std::endl;
76               
77                unsigned int nextImageIndex = (_currentImageIndex+1)%_imageBuffer.size();
78                unsigned int nextPboIndex = (_currentPboIndex+1)%_pboBuffer.size();
79
80                int width=0, height=0;
81                getSize(_gc, width, height);
82                if (width!=_width || _height!=height)
83                {
84                    std::cout<<"   Window resized "<<width<<", "<<height<<std::endl;
85                    _width = width;
86                    _height = height;
87                }
88               
89                osg::Image* image = _imageBuffer[_currentImageIndex].get();
90               
91                image->readPixels(0,0,_width,_height,
92                                  _pixelFormat,_type);
93                                   
94                if (!_fileName.empty())
95                {
96                    osgDB::writeImageFile(*image, _fileName);
97                }
98               
99                _currentImageIndex = nextImageIndex;
100                _currentPboIndex = nextPboIndex;
101
102            }
103       
104            typedef std::vector< osg::ref_ptr<osg::Image> >             ImageBuffer;
105            typedef std::vector< osg::ref_ptr<osg::PixelBufferObject> > PBOBuffer;
106       
107            osg::GraphicsContext*   _gc;
108            std::string             _fileName;
109           
110            GLenum                  _pixelFormat;
111            GLenum                  _type;
112            int                     _width;
113            int                     _height;
114           
115            unsigned int            _currentImageIndex;
116            ImageBuffer             _imageBuffer;
117           
118            unsigned int            _currentPboIndex;
119            PBOBuffer               _pboBuffer;
120        };
121   
122        WindowCaptureCallback()
123        {
124        }
125
126        ContextData* createContextData(osg::GraphicsContext* gc) const
127        {
128            std::stringstream filename;
129            filename << "test_"<<_contextDataMap.size()<<".jpg";
130            return new ContextData(gc,filename.str());
131        }
132       
133        ContextData* getContextData(osg::GraphicsContext* gc) const
134        {
135            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
136            osg::ref_ptr<ContextData>& data = _contextDataMap[gc];
137            if (!data) data = createContextData(gc);
138           
139            return data.get();
140        }
141
142        virtual void operator () (osg::RenderInfo& renderInfo) const
143        {
144            osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
145            osg::notify(osg::NOTICE)<<"Capture screen image "<<gc<<std::endl;
146           
147            osg::ref_ptr<ContextData> cd = getContextData(gc);
148            cd->read();
149        }
150       
151        typedef std::map<osg::GraphicsContext*, osg::ref_ptr<ContextData> > ContextDataMap;
152       
153        mutable OpenThreads::Mutex  _mutex;
154        mutable ContextDataMap      _contextDataMap;
155       
156};
157
158void addCallbackToViewer(osgViewer::ViewerBase& viewer, WindowCaptureCallback* callback)
159{
160    osgViewer::ViewerBase::Windows windows;
161    viewer.getWindows(windows);
162    for(osgViewer::ViewerBase::Windows::iterator itr = windows.begin();
163        itr != windows.end();
164        ++itr)
165    {
166        osgViewer::GraphicsWindow* window = *itr;
167        osg::GraphicsContext::Cameras& cameras = window->getCameras();
168        osg::Camera* lastCamera = 0;
169        for(osg::GraphicsContext::Cameras::iterator cam_itr = cameras.begin();
170            cam_itr != cameras.end();
171            ++cam_itr)
172        {
173            if (lastCamera)
174            {
175                if ((*cam_itr)->getRenderOrder() > (*cam_itr)->getRenderOrder())
176                {
177                    lastCamera = (*cam_itr);
178                }
179                if ((*cam_itr)->getRenderOrder() == lastCamera->getRenderOrder() &&
180                    (*cam_itr)->getRenderOrderNum() >= lastCamera->getRenderOrderNum())
181                {
182                    lastCamera = (*cam_itr);
183                }
184            }
185            else
186            {
187                lastCamera = *cam_itr;
188            }
189        }
190       
191        if (lastCamera)
192        {
193            osg::notify(osg::NOTICE)<<"Last camera "<<lastCamera<<std::endl;
194           
195            lastCamera->setFinalDrawCallback(callback);
196        }
197        else
198        {
199            osg::notify(osg::NOTICE)<<"No camera found"<<std::endl;
200        }
201    }
202}
203
204int main(int argc, char** argv)
205{
206    // use an ArgumentParser object to manage the program arguments.
207    osg::ArgumentParser arguments(&argc,argv);
208
209    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
210    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
211    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
212    arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad");
213    arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField");
214
215    osgViewer::Viewer viewer(arguments);
216
217    unsigned int helpType = 0;
218    if ((helpType = arguments.readHelpType()))
219    {
220        arguments.getApplicationUsage()->write(std::cout, helpType);
221        return 1;
222    }
223   
224    // report any errors if they have occurred when parsing the program arguments.
225    if (arguments.errors())
226    {
227        arguments.writeErrorMessages(std::cout);
228        return 1;
229    }
230   
231    if (arguments.argc()<=1)
232    {
233        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
234        return 1;
235    }
236
237    // set up the camera manipulators.
238    {
239        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
240
241        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
242        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
243        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
244        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
245
246        std::string pathfile;
247        char keyForAnimationPath = '5';
248        while (arguments.read("-p",pathfile))
249        {
250            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
251            if (apm || !apm->valid())
252            {
253                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
254                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
255                keyswitchManipulator->selectMatrixManipulator(num);
256                ++keyForAnimationPath;
257            }
258        }
259
260        viewer.setCameraManipulator( keyswitchManipulator.get() );
261    }
262
263    // add the state manipulator
264    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
265   
266    // add the thread model handler
267    viewer.addEventHandler(new osgViewer::ThreadingHandler);
268
269    // add the window size toggle handler
270    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
271       
272    // add the stats handler
273    viewer.addEventHandler(new osgViewer::StatsHandler);
274
275    // add the help handler
276    viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
277
278    // add the record camera path handler
279    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
280
281    // add the LOD Scale handler
282    viewer.addEventHandler(new osgViewer::LODScaleHandler);
283
284    // load the data
285    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
286    if (!loadedModel)
287    {
288        std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl;
289        return 1;
290    }
291
292    // any option left unread are converted into errors to write out later.
293    arguments.reportRemainingOptionsAsUnrecognized();
294
295    // report any errors if they have occurred when parsing the program arguments.
296    if (arguments.errors())
297    {
298        arguments.writeErrorMessages(std::cout);
299        return 1;
300    }
301
302
303    // optimize the scene graph, remove redundant nodes and state etc.
304    osgUtil::Optimizer optimizer;
305    optimizer.optimize(loadedModel.get());
306
307    viewer.setSceneData( loadedModel.get() );
308
309    viewer.realize();
310   
311    addCallbackToViewer(viewer, new WindowCaptureCallback);
312
313    return viewer.run();
314
315}
Note: See TracBrowser for help on using the browser.