root/OpenSceneGraph/trunk/examples/osgimagesequence/osgimagesequence.cpp @ 13158

Revision 13158, 15.4 kB (checked in by robert, 3 hours ago)

From Aitor Moreno, LAS plugin - depends upon boost and liblas and liblas-c

  • Property svn:eol-style set to native
Line 
1/* OpenSceneGraph example, osgtexture3D.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osg/Node>
20#include <osg/Geometry>
21#include <osg/Notify>
22#include <osg/Texture1D>
23#include <osg/Texture2D>
24#include <osg/Texture3D>
25#include <osg/TextureRectangle>
26#include <osg/ImageSequence>
27#include <osg/Geode>
28
29#include <osgDB/Registry>
30#include <osgDB/ReadFile>
31#include <osgDB/WriteFile>
32#include <osgDB/FileNameUtils>
33#include <osgDB/FileUtils>
34
35
36#include <osgViewer/Viewer>
37#include <osgViewer/ViewerEventHandlers>
38
39#include <iostream>
40
41
42static osgDB::DirectoryContents getSuitableFiles(osg::ArgumentParser& arguments)
43{
44    osgDB::DirectoryContents files;
45    for(int i=1; i<arguments.argc(); ++i)
46    {
47        if (osgDB::fileType(arguments[i]) == osgDB::DIRECTORY)
48        {
49            const std::string& directory = arguments[i];
50            osgDB::DirectoryContents dc = osgDB::getSortedDirectoryContents(directory);
51           
52            for(osgDB::DirectoryContents::iterator itr = dc.begin(); itr != dc.end(); ++itr)
53            {
54                std::string full_file_name = directory + "/" + (*itr);
55                std::string ext = osgDB::getLowerCaseFileExtension(full_file_name);
56                if ((ext == "jpg") || (ext == "png") || (ext == "gif") ||  (ext == "rgb") || (ext == "dds") )
57                {
58                    files.push_back(full_file_name);
59                }
60            }
61        }
62        else {
63            files.push_back(arguments[i]);
64        }
65    }
66    return files;
67}
68
69
70//
71// A simple demo demonstrating how to set on an animated texture using an osg::ImageSequence
72//
73
74osg::StateSet* createState(osg::ArgumentParser& arguments)
75{
76    osg::ref_ptr<osg::ImageSequence> imageSequence = new osg::ImageSequence;
77
78    bool preLoad = true;
79       
80    while (arguments.read("--page-and-discard"))
81    {
82        imageSequence->setMode(osg::ImageSequence::PAGE_AND_DISCARD_USED_IMAGES);
83        preLoad = false;
84    }
85   
86    while (arguments.read("--page-and-retain"))
87    {
88        imageSequence->setMode(osg::ImageSequence::PAGE_AND_RETAIN_IMAGES);
89        preLoad = false;
90    }
91   
92    while (arguments.read("--preload"))
93    {
94        imageSequence->setMode(osg::ImageSequence::PRE_LOAD_ALL_IMAGES);
95        preLoad = true;
96    }
97   
98    double length = -1.0;
99    while (arguments.read("--length",length)) {}
100   
101    double fps = 30.0;
102    while (arguments.read("--fps",fps)) {}
103
104    osgDB::DirectoryContents files = getSuitableFiles(arguments);
105    if (!files.empty())
106    {
107        for(osgDB::DirectoryContents::iterator itr = files.begin();
108            itr != files.end();
109            ++itr)
110        {
111            const std::string& filename = *itr;
112            if (preLoad)
113            {
114                osg::ref_ptr<osg::Image> image = osgDB::readImageFile(filename);
115                if (image.valid())
116                {
117                    imageSequence->addImage(image.get());
118                }
119            }
120            else
121            {
122                imageSequence->addImageFile(filename);
123            }
124
125        }
126       
127        if (length>0.0)
128        {
129            imageSequence->setLength(length);
130        }
131        else
132        {
133            unsigned int maxNum = osg::maximum(imageSequence->getFileNames().size(),
134                                               imageSequence->getImages().size());
135                                               
136            imageSequence->setLength(double(maxNum)*(1.0/fps));
137        }
138    }
139    else
140    {
141        if (length>0.0)
142        {
143            imageSequence->setLength(length);
144        }
145        else
146        {
147            imageSequence->setLength(4.0);
148        }
149        imageSequence->addImage(osgDB::readImageFile("Cubemap_axis/posx.png"));
150        imageSequence->addImage(osgDB::readImageFile("Cubemap_axis/negx.png"));
151        imageSequence->addImage(osgDB::readImageFile("Cubemap_axis/posy.png"));
152        imageSequence->addImage(osgDB::readImageFile("Cubemap_axis/negy.png"));
153        imageSequence->addImage(osgDB::readImageFile("Cubemap_axis/posz.png"));
154        imageSequence->addImage(osgDB::readImageFile("Cubemap_axis/negz.png"));
155    }
156       
157    // start the image sequence playing
158    imageSequence->play();
159
160#if 1
161    osg::Texture2D* texture = new osg::Texture2D;
162    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
163    texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
164    texture->setWrap(osg::Texture::WRAP_R,osg::Texture::REPEAT);
165    texture->setResizeNonPowerOfTwoHint(false);
166    texture->setImage(imageSequence.get());
167    //texture->setTextureSize(512,512);
168#else   
169    osg::TextureRectangle* texture = new osg::TextureRectangle;
170    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
171    texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
172    texture->setWrap(osg::Texture::WRAP_R,osg::Texture::REPEAT);
173    texture->setImage(imageSequence.get());
174    //texture->setTextureSize(512,512);
175#endif
176
177    // create the StateSet to store the texture data
178    osg::StateSet* stateset = new osg::StateSet;
179
180    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
181
182    return stateset;
183}
184
185osg::Node* createModel(osg::ArgumentParser& arguments)
186{
187
188    // create the geometry of the model, just a simple 2d quad right now.   
189    osg::Geode* geode = new osg::Geode;
190    geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0), osg::Vec3(1.0f,0.0f,0.0), osg::Vec3(0.0f,0.0f,1.0f)));
191
192    geode->setStateSet(createState(arguments));
193   
194    return geode;
195
196}
197
198
199osg::ImageStream* s_imageStream = 0;
200class MovieEventHandler : public osgGA::GUIEventHandler
201{
202public:
203
204    MovieEventHandler():_playToggle(true),_trackMouse(false) {}
205   
206    void setMouseTracking(bool track) { _trackMouse = track; }
207    bool getMouseTracking() const { return _trackMouse; }
208   
209    void set(osg::Node* node);
210
211    void setTrackMouse(bool tm)
212    {
213        if (tm==_trackMouse) return;
214
215        _trackMouse = tm;
216
217        std::cout << "tracking mouse: " << (_trackMouse ? "ON" : "OFF") << std::endl;
218
219        for(ImageStreamList::iterator itr=_imageStreamList.begin();
220            itr!=_imageStreamList.end();
221            ++itr)
222        {
223            if ((*itr)->getStatus()==osg::ImageStream::PLAYING)
224            {
225                (*itr)->pause();
226            }
227            else
228            {
229                (*itr)->play();
230            }
231        }
232
233    }
234
235    bool getTrackMouse() const { return _trackMouse; }
236
237    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
238   
239    virtual void getUsage(osg::ApplicationUsage& usage) const;
240
241    typedef std::vector< osg::observer_ptr<osg::ImageStream> > ImageStreamList;
242   
243    struct ImageStreamPlaybackSpeedData {
244        double fps;
245        unsigned char* lastData;
246        double timeStamp, lastOutput;
247       
248        ImageStreamPlaybackSpeedData() : fps(0), lastData(NULL), timeStamp(0), lastOutput(0) {}
249       
250    };
251   
252    typedef std::vector< ImageStreamPlaybackSpeedData > ImageStreamPlayBackSpeedList;
253
254protected:
255
256    virtual ~MovieEventHandler() {}
257
258    class FindImageStreamsVisitor : public osg::NodeVisitor
259    {
260    public:
261        FindImageStreamsVisitor(ImageStreamList& imageStreamList):
262            _imageStreamList(imageStreamList) {}
263           
264        virtual void apply(osg::Geode& geode)
265        {
266            apply(geode.getStateSet());
267
268            for(unsigned int i=0;i<geode.getNumDrawables();++i)
269            {
270                apply(geode.getDrawable(i)->getStateSet());
271            }
272       
273            traverse(geode);
274        }
275
276        virtual void apply(osg::Node& node)
277        {
278            apply(node.getStateSet());
279            traverse(node);
280        }
281       
282        inline void apply(osg::StateSet* stateset)
283        {
284            if (!stateset) return;
285           
286            osg::StateAttribute* attr = stateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
287            if (attr)
288            {
289                osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(attr);
290                if (texture2D) apply(dynamic_cast<osg::ImageStream*>(texture2D->getImage()));
291
292                osg::TextureRectangle* textureRec = dynamic_cast<osg::TextureRectangle*>(attr);
293                if (textureRec) apply(dynamic_cast<osg::ImageStream*>(textureRec->getImage()));
294            }
295        }
296       
297        inline void apply(osg::ImageStream* imagestream)
298        {
299            if (imagestream)
300            {
301                _imageStreamList.push_back(imagestream);
302                s_imageStream = imagestream;
303            }
304        }
305       
306        ImageStreamList& _imageStreamList;
307       
308    protected:
309   
310        FindImageStreamsVisitor& operator = (const FindImageStreamsVisitor&) { return *this; }
311    };
312
313
314    bool            _playToggle;
315    bool            _trackMouse;
316    ImageStreamList _imageStreamList;
317    ImageStreamPlayBackSpeedList _imageStreamPlayBackSpeedList;
318   
319};
320
321
322
323void MovieEventHandler::set(osg::Node* node)
324{
325    _imageStreamList.clear();
326    if (node)
327    {
328        FindImageStreamsVisitor fisv(_imageStreamList);
329        node->accept(fisv);
330    }
331    _imageStreamPlayBackSpeedList.resize(_imageStreamList.size());
332}
333
334
335bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
336{
337    switch(ea.getEventType())
338    {
339        case(osgGA::GUIEventAdapter::FRAME):
340            {
341                double t = ea.getTime();
342                bool printed(false);
343               
344                ImageStreamPlayBackSpeedList::iterator fps_itr = _imageStreamPlayBackSpeedList.begin();
345                for(ImageStreamList::iterator itr=_imageStreamList.begin();
346                    itr!=_imageStreamList.end();
347                    ++itr, ++fps_itr)
348                {
349                    if (((*itr)->getStatus()==osg::ImageStream::PLAYING) && ((*itr)->data() != (*fps_itr).lastData))
350                    {
351                        ImageStreamPlaybackSpeedData& data(*fps_itr);
352                        double dt = (data.timeStamp > 0) ? t - data.timeStamp : 1/60.0;
353                        data.lastData = (*itr)->data();
354                        data.fps = (*fps_itr).fps * 0.8 + 0.2 * (1/dt);
355                        data.timeStamp = t;
356                       
357                        if (t-data.lastOutput > 1)
358                        {
359                            std::cout << data.fps << " ";
360                            data.lastOutput = t;
361                            printed = true;
362                        }
363                       
364                    }
365                }
366                if (printed)
367                    std::cout << std::endl;
368            }
369            break;
370        case(osgGA::GUIEventAdapter::MOVE):
371            {
372                if (_trackMouse)
373                {
374                    for(ImageStreamList::iterator itr=_imageStreamList.begin();
375                        itr!=_imageStreamList.end();
376                        ++itr)
377                    {
378                        double dt = (*itr)->getLength() * ((1.0+ea.getXnormalized()) / 2.0);
379                        (*itr)->seek(dt);
380                        std::cout << "seeking to " << dt << " length: " <<(*itr)->getLength() << std::endl;
381                    }
382                }
383                return false;
384            }
385           
386        case(osgGA::GUIEventAdapter::KEYDOWN):
387        {
388            if (ea.getKey()=='p')
389            {
390                for(ImageStreamList::iterator itr=_imageStreamList.begin();
391                    itr!=_imageStreamList.end();
392                    ++itr)
393                {
394                    if ((*itr)->getStatus()==osg::ImageStream::PLAYING)
395                    {
396                        // playing, so pause
397                        std::cout<<"Pause"<<std::endl;
398                        (*itr)->pause();
399                    }
400                    else
401                    {
402                        // playing, so pause
403                        std::cout<<"Play"<<std::endl;
404                        (*itr)->play();
405                    }
406                }
407                return true;
408            }
409            else if (ea.getKey()=='r')
410            {
411                for(ImageStreamList::iterator itr=_imageStreamList.begin();
412                    itr!=_imageStreamList.end();
413                    ++itr)
414                {
415                    std::cout<<"Restart"<<std::endl;
416                    (*itr)->rewind();
417                }
418                return true;
419            }
420            else if (ea.getKey()=='L')
421            {
422                for(ImageStreamList::iterator itr=_imageStreamList.begin();
423                    itr!=_imageStreamList.end();
424                    ++itr)
425                {
426                    if ( (*itr)->getLoopingMode() == osg::ImageStream::LOOPING)
427                    {
428                        std::cout<<"Toggle Looping Off"<<std::endl;
429                        (*itr)->setLoopingMode( osg::ImageStream::NO_LOOPING );
430                    }
431                    else
432                    {
433                        std::cout<<"Toggle Looping On"<<std::endl;
434                        (*itr)->setLoopingMode( osg::ImageStream::LOOPING );
435                    }
436                }
437                return true;
438            }
439            else if (ea.getKey() == 'i')
440            {
441                setTrackMouse(!_trackMouse);
442               
443               
444            }
445            return false;
446        }
447
448        default:
449            return false;
450    }
451
452    return false;
453}
454
455void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
456{
457    usage.addKeyboardMouseBinding("i","toggle interactive mode, scrub via mouse-move");
458    usage.addKeyboardMouseBinding("p","Play/Pause movie");
459    usage.addKeyboardMouseBinding("r","Restart movie");
460    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
461}
462
463
464
465
466int main(int argc, char **argv)
467{
468    osg::ArgumentParser arguments(&argc,argv);
469
470    // construct the viewer.
471    osgViewer::Viewer viewer(arguments);
472
473    std::string filename;
474    arguments.read("-o",filename);
475
476    // create a model from the images and pass it to the viewer.
477    viewer.setSceneData(createModel(arguments));
478
479    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
480    MovieEventHandler* meh = new MovieEventHandler();
481    meh->set( viewer.getSceneData() );
482
483    if (arguments.read("--track-mouse")) meh->setTrackMouse(true);
484   
485    viewer.addEventHandler( meh );
486
487    viewer.addEventHandler( new osgViewer::StatsHandler());
488
489    if (!filename.empty())
490    {
491        osgDB::writeNodeFile(*viewer.getSceneData(),filename);
492    }
493
494    return viewer.run();
495}
Note: See TracBrowser for help on using the browser.