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

Revision 13143, 15.3 kB (checked in by robert, 10 days ago)

Added shaders to support experimental shader based displacement mapping technique osgTerrain::ShaderTerrain?.

  • 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    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
212   
213    virtual void getUsage(osg::ApplicationUsage& usage) const;
214
215    typedef std::vector< osg::observer_ptr<osg::ImageStream> > ImageStreamList;
216   
217    struct ImageStreamPlaybackSpeedData {
218        double fps;
219        unsigned char* lastData;
220        double timeStamp, lastOutput;
221       
222        ImageStreamPlaybackSpeedData() : fps(0), lastData(NULL), timeStamp(0), lastOutput(0) {}
223       
224    };
225   
226    typedef std::vector< ImageStreamPlaybackSpeedData > ImageStreamPlayBackSpeedList;
227
228protected:
229
230    virtual ~MovieEventHandler() {}
231
232    class FindImageStreamsVisitor : public osg::NodeVisitor
233    {
234    public:
235        FindImageStreamsVisitor(ImageStreamList& imageStreamList):
236            _imageStreamList(imageStreamList) {}
237           
238        virtual void apply(osg::Geode& geode)
239        {
240            apply(geode.getStateSet());
241
242            for(unsigned int i=0;i<geode.getNumDrawables();++i)
243            {
244                apply(geode.getDrawable(i)->getStateSet());
245            }
246       
247            traverse(geode);
248        }
249
250        virtual void apply(osg::Node& node)
251        {
252            apply(node.getStateSet());
253            traverse(node);
254        }
255       
256        inline void apply(osg::StateSet* stateset)
257        {
258            if (!stateset) return;
259           
260            osg::StateAttribute* attr = stateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
261            if (attr)
262            {
263                osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(attr);
264                if (texture2D) apply(dynamic_cast<osg::ImageStream*>(texture2D->getImage()));
265
266                osg::TextureRectangle* textureRec = dynamic_cast<osg::TextureRectangle*>(attr);
267                if (textureRec) apply(dynamic_cast<osg::ImageStream*>(textureRec->getImage()));
268            }
269        }
270       
271        inline void apply(osg::ImageStream* imagestream)
272        {
273            if (imagestream)
274            {
275                _imageStreamList.push_back(imagestream);
276                s_imageStream = imagestream;
277            }
278        }
279       
280        ImageStreamList& _imageStreamList;
281       
282    protected:
283   
284        FindImageStreamsVisitor& operator = (const FindImageStreamsVisitor&) { return *this; }
285    };
286
287
288    bool            _playToggle;
289    bool            _trackMouse;
290    ImageStreamList _imageStreamList;
291    ImageStreamPlayBackSpeedList _imageStreamPlayBackSpeedList;
292   
293};
294
295
296
297void MovieEventHandler::set(osg::Node* node)
298{
299    _imageStreamList.clear();
300    if (node)
301    {
302        FindImageStreamsVisitor fisv(_imageStreamList);
303        node->accept(fisv);
304    }
305    _imageStreamPlayBackSpeedList.resize(_imageStreamList.size());
306}
307
308
309bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
310{
311    switch(ea.getEventType())
312    {
313        case(osgGA::GUIEventAdapter::FRAME):
314            {
315                double t = ea.getTime();
316                bool printed(false);
317               
318                ImageStreamPlayBackSpeedList::iterator fps_itr = _imageStreamPlayBackSpeedList.begin();
319                for(ImageStreamList::iterator itr=_imageStreamList.begin();
320                    itr!=_imageStreamList.end();
321                    ++itr, ++fps_itr)
322                {
323                    if (((*itr)->getStatus()==osg::ImageStream::PLAYING) && ((*itr)->data() != (*fps_itr).lastData))
324                    {
325                        ImageStreamPlaybackSpeedData& data(*fps_itr);
326                        double dt = (data.timeStamp > 0) ? t - data.timeStamp : 1/60.0;
327                        data.lastData = (*itr)->data();
328                        data.fps = (*fps_itr).fps * 0.8 + 0.2 * (1/dt);
329                        data.timeStamp = t;
330                       
331                        if (t-data.lastOutput > 1)
332                        {
333                            std::cout << data.fps << " ";
334                            data.lastOutput = t;
335                            printed = true;
336                        }
337                       
338                    }
339                }
340                if (printed)
341                    std::cout << std::endl;
342            }
343            break;
344        case(osgGA::GUIEventAdapter::MOVE):
345            {
346                if (_trackMouse)
347                {
348                    for(ImageStreamList::iterator itr=_imageStreamList.begin();
349                        itr!=_imageStreamList.end();
350                        ++itr)
351                    {
352                        double dt = (*itr)->getLength() * ((1.0+ea.getXnormalized()) / 2.0);
353                        (*itr)->seek(dt);
354                        std::cout << "seeking to " << dt << " length: " <<(*itr)->getLength() << std::endl;
355                    }
356                }
357                return false;
358            }
359           
360        case(osgGA::GUIEventAdapter::KEYDOWN):
361        {
362            if (ea.getKey()=='p')
363            {
364                for(ImageStreamList::iterator itr=_imageStreamList.begin();
365                    itr!=_imageStreamList.end();
366                    ++itr)
367                {
368                    if ((*itr)->getStatus()==osg::ImageStream::PLAYING)
369                    {
370                        // playing, so pause
371                        std::cout<<"Pause"<<std::endl;
372                        (*itr)->pause();
373                    }
374                    else
375                    {
376                        // playing, so pause
377                        std::cout<<"Play"<<std::endl;
378                        (*itr)->play();
379                    }
380                }
381                return true;
382            }
383            else if (ea.getKey()=='r')
384            {
385                for(ImageStreamList::iterator itr=_imageStreamList.begin();
386                    itr!=_imageStreamList.end();
387                    ++itr)
388                {
389                    std::cout<<"Restart"<<std::endl;
390                    (*itr)->rewind();
391                }
392                return true;
393            }
394            else if (ea.getKey()=='L')
395            {
396                for(ImageStreamList::iterator itr=_imageStreamList.begin();
397                    itr!=_imageStreamList.end();
398                    ++itr)
399                {
400                    if ( (*itr)->getLoopingMode() == osg::ImageStream::LOOPING)
401                    {
402                        std::cout<<"Toggle Looping Off"<<std::endl;
403                        (*itr)->setLoopingMode( osg::ImageStream::NO_LOOPING );
404                    }
405                    else
406                    {
407                        std::cout<<"Toggle Looping On"<<std::endl;
408                        (*itr)->setLoopingMode( osg::ImageStream::LOOPING );
409                    }
410                }
411                return true;
412            }
413            else if (ea.getKey() == 'i')
414            {
415                _trackMouse = !_trackMouse;
416                std::cout << "tracking mouse: " << (_trackMouse ? "ON" : "OFF") << std::endl;
417               
418                for(ImageStreamList::iterator itr=_imageStreamList.begin();
419                    itr!=_imageStreamList.end();
420                    ++itr)
421                {
422                    if ((*itr)->getStatus()==osg::ImageStream::PLAYING)
423                    {
424                        (*itr)->pause();
425                    }
426                    else
427                    {
428                        (*itr)->play();
429                    }
430                }
431               
432               
433            }
434            return false;
435        }
436
437        default:
438            return false;
439    }
440
441    return false;
442}
443
444void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
445{
446    usage.addKeyboardMouseBinding("i","toggle interactive mode, scrub via mouse-move");
447    usage.addKeyboardMouseBinding("p","Play/Pause movie");
448    usage.addKeyboardMouseBinding("r","Restart movie");
449    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
450}
451
452
453
454
455int main(int argc, char **argv)
456{
457    osg::ArgumentParser arguments(&argc,argv);
458
459    // construct the viewer.
460    osgViewer::Viewer viewer(arguments);
461
462    std::string filename;
463    arguments.read("-o",filename);
464
465    // create a model from the images and pass it to the viewer.
466    viewer.setSceneData(createModel(arguments));
467
468    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
469    MovieEventHandler* meh = new MovieEventHandler();
470    meh->set( viewer.getSceneData() );
471    viewer.addEventHandler( meh );
472
473    viewer.addEventHandler( new osgViewer::StatsHandler());
474
475    if (!filename.empty())
476    {
477        osgDB::writeNodeFile(*viewer.getSceneData(),filename);
478    }
479
480    return viewer.run();
481}
Note: See TracBrowser for help on using the browser.