root/OpenSceneGraph/trunk/examples/osgmovie/osgmovie.cpp @ 4738

Revision 4738, 12.8 kB (checked in by robert, 9 years ago)

Fixes for dumb VS6.0 compiler

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// -*-c++-*-
2
3#include <osgProducer/Viewer>
4
5#include <osgDB/ReadFile>
6
7#include <osg/Geode>
8#include <osg/Geometry>
9#include <osg/StateSet>
10#include <osg/Material>
11#include <osg/Texture2D>
12#include <osg/TextureRectangle>
13#include <osg/TexMat>
14#include <osg/CullFace>
15#include <osg/ImageStream>
16
17#include <osgGA/TrackballManipulator>
18
19osg::ImageStream* s_imageStream = 0;
20class PostSwapFinishCallback : public Producer::Camera::Callback
21{
22public:
23
24    PostSwapFinishCallback() {}
25
26    virtual void operator()(const Producer::Camera& camera)
27    {
28        // osg::Timer_t start_tick = osg::Timer::instance()->tick();
29       
30        osgProducer::OsgSceneHandler* sh = const_cast<osgProducer::OsgSceneHandler*>(dynamic_cast<const osgProducer::OsgSceneHandler*>(camera.getSceneHandler()));
31   
32        if (s_imageStream && s_imageStream->getPixelBufferObject()) s_imageStream->getPixelBufferObject()->compileBuffer(*(sh->getSceneView()->getState()));
33        // glFinish();
34
35        //osg::notify(osg::NOTICE)<<"callback after PBO "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
36    }
37};
38
39class MovieEventHandler : public osgGA::GUIEventHandler
40{
41public:
42
43    MovieEventHandler() {}
44   
45    void set(osg::Node* node);
46
47    virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }
48
49    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
50   
51    virtual void getUsage(osg::ApplicationUsage& usage) const;
52
53    typedef std::vector< osg::ref_ptr<osg::ImageStream> > ImageStreamList;
54
55protected:
56
57    virtual ~MovieEventHandler() {}
58
59    class FindImageStreamsVisitor : public osg::NodeVisitor
60    {
61    public:
62        FindImageStreamsVisitor(ImageStreamList& imageStreamList):
63            _imageStreamList(imageStreamList) {}
64           
65        virtual void apply(osg::Geode& geode)
66        {
67            apply(geode.getStateSet());
68
69            for(unsigned int i=0;i<geode.getNumDrawables();++i)
70            {
71                apply(geode.getDrawable(i)->getStateSet());
72            }
73       
74            traverse(geode);
75        }
76
77        virtual void apply(osg::Node& node)
78        {
79            apply(node.getStateSet());
80            traverse(node);
81        }
82       
83        inline void apply(osg::StateSet* stateset)
84        {
85            if (!stateset) return;
86           
87            osg::StateAttribute* attr = stateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
88            if (attr)
89            {
90                osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(attr);
91                if (texture2D) apply(dynamic_cast<osg::ImageStream*>(texture2D->getImage()));
92
93                osg::TextureRectangle* textureRec = dynamic_cast<osg::TextureRectangle*>(attr);
94                if (textureRec) apply(dynamic_cast<osg::ImageStream*>(textureRec->getImage()));
95            }
96        }
97       
98        inline void apply(osg::ImageStream* imagestream)
99        {
100            if (imagestream)
101            {
102                _imageStreamList.push_back(imagestream);
103                s_imageStream = imagestream;
104            }
105        }
106       
107        ImageStreamList& _imageStreamList;
108    };
109
110
111    ImageStreamList _imageStreamList;
112   
113};
114
115
116
117void MovieEventHandler::set(osg::Node* node)
118{
119    _imageStreamList.clear();
120    if (node)
121    {
122        FindImageStreamsVisitor fisv(_imageStreamList);
123        node->accept(fisv);
124    }
125}
126
127
128bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
129{
130    switch(ea.getEventType())
131    {
132        case(osgGA::GUIEventAdapter::KEYDOWN):
133        {
134            if (ea.getKey()=='s')
135            {
136                for(ImageStreamList::iterator itr=_imageStreamList.begin();
137                    itr!=_imageStreamList.end();
138                    ++itr)
139                {
140                    std::cout<<"Play"<<std::endl;
141                     (*itr)->play();
142                }
143                return true;
144            }
145            else if (ea.getKey()=='p')
146            {
147                for(ImageStreamList::iterator itr=_imageStreamList.begin();
148                    itr!=_imageStreamList.end();
149                    ++itr)
150                {
151                    std::cout<<"Pause"<<std::endl;
152                    (*itr)->pause();
153                }
154                return true;
155            }
156            else if (ea.getKey()=='r')
157            {
158                for(ImageStreamList::iterator itr=_imageStreamList.begin();
159                    itr!=_imageStreamList.end();
160                    ++itr)
161                {
162                    std::cout<<"Restart"<<std::endl;
163                    (*itr)->rewind();
164                    (*itr)->play();
165                }
166                return true;
167            }
168            else if (ea.getKey()=='l')
169            {
170                for(ImageStreamList::iterator itr=_imageStreamList.begin();
171                    itr!=_imageStreamList.end();
172                    ++itr)
173                {
174                    if ( (*itr)->getLoopingMode() == osg::ImageStream::LOOPING)
175                    {
176                        std::cout<<"Toggle Looping Off"<<std::endl;
177                        (*itr)->setLoopingMode( osg::ImageStream::NO_LOOPING );
178                    }
179                    else
180                    {
181                        std::cout<<"Toggle Looping On"<<std::endl;
182                        (*itr)->setLoopingMode( osg::ImageStream::LOOPING );
183                    }
184                }
185                return true;
186            }
187            return false;
188        }
189
190        default:
191            return false;
192    }
193}
194
195void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
196{
197    usage.addKeyboardMouseBinding("p","Pause movie");
198    usage.addKeyboardMouseBinding("s","Play movie");
199    usage.addKeyboardMouseBinding("r","Restart movie");
200    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
201}
202
203
204osg::Geometry* myCreateTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image, bool useTextureRectangle)
205{
206    if (useTextureRectangle)
207    {
208        osg::Geometry* pictureQuad = createTexturedQuadGeometry(pos,
209                                           osg::Vec3(width,0.0f,0.0f),
210                                           osg::Vec3(0.0f,0.0f,height),
211                                           0.0f,image->t(), image->s(),0.0f);
212
213        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
214                    new osg::TextureRectangle(image),
215                    osg::StateAttribute::ON);
216                   
217        return pictureQuad;
218    }
219    else
220    {
221        osg::Geometry* pictureQuad = createTexturedQuadGeometry(pos,
222                                           osg::Vec3(width,0.0f,0.0f),
223                                           osg::Vec3(0.0f,0.0f,height),
224                                           0.0f,1.0f, 1.0f,0.0f);
225                                   
226        osg::Texture2D* texture = new osg::Texture2D(image);
227        texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); 
228                                       
229        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
230                    texture,
231                    osg::StateAttribute::ON);
232
233        return pictureQuad;
234    }
235}
236
237int main(int argc, char** argv)
238{
239    // use an ArgumentParser object to manage the program arguments.
240    osg::ArgumentParser arguments(&argc,argv);
241   
242    // set up the usage document, in case we need to print out how to use this program.
243    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
244    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
245    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
246    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
247   
248    bool useTextureRectangle = true;
249    bool useShader = false;
250
251    // construct the viewer.
252    osgProducer::Viewer viewer(arguments);
253   
254    while (arguments.read("--texture2D")) useTextureRectangle=false;
255    while (arguments.read("--shader")) useShader=true;
256
257    // set up the value with sensible default event handlers.
258    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
259
260    // register the handler to add keyboard and mosue handling.
261    MovieEventHandler* meh = new MovieEventHandler();
262    viewer.getEventHandlerList().push_front(meh);
263
264
265    // get details on keyboard and mouse bindings used by the viewer.
266    viewer.getUsage(*arguments.getApplicationUsage());
267
268    // if user request help write it out to cout.
269    if (arguments.read("-h") || arguments.read("--help"))
270    {
271        arguments.getApplicationUsage()->write(std::cout);
272        return 1;
273    }
274
275    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
276    osg::Vec3 pos(0.0f,0.0f,0.0f);
277       
278    osg::StateSet* stateset = geode->getOrCreateStateSet();
279    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
280
281    if (useShader)
282    {
283        //useTextureRectangle = false;
284       
285        static const char *shaderSourceTextureRec = {
286            "uniform vec4 cutoff_color;\n"
287            "uniform samplerRect movie_texture;\n"
288            "void main(void)\n"
289            "{\n"
290            "    vec4 texture_color = textureRect(movie_texture, gl_TexCoord[0]); \n"
291            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
292            "    gl_FragColor = texture_color;\n"
293            "}\n"
294        };
295
296        static const char *shaderSourceTexture2D = {
297            "uniform vec4 cutoff_color;\n"
298            "uniform sampler2D movie_texture;\n"
299            "void main(void)\n"
300            "{\n"
301            "    vec4 texture_color = texture2D(movie_texture, gl_TexCoord[0]); \n"
302            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
303            "    gl_FragColor = texture_color;\n"
304            "}\n"
305        };
306
307        osg::Program* program = new osg::Program;
308       
309        program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
310                                           useTextureRectangle ? shaderSourceTextureRec : shaderSourceTexture2D));
311
312        stateset->addUniform(new osg::Uniform("cutoff_color",osg::Vec4(0.1f,0.1f,0.1f,1.0f)));
313        stateset->addUniform(new osg::Uniform("movie_texture",0));
314
315        stateset->setAttribute(program);
316
317    }
318
319
320    for(int i=1;i<arguments.argc();++i)
321    {
322        if (arguments.isString(i))
323        {
324            osg::Image* image = osgDB::readImageFile(arguments[i]);
325            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
326            if (imagestream) imagestream->play();
327           
328            if (image)
329            {
330                geode->addDrawable(myCreateTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle));
331               
332                pos.z() += image->t()*1.5f;
333            }
334            else
335            {
336                std::cout<<"Unable to read file "<<arguments[i]<<std::endl;
337            }           
338        }
339    }
340   
341    if (geode->getNumDrawables()==0)
342    {
343        // nothing loaded.
344        return 1;
345    }
346
347    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
348    meh->set(geode.get());
349
350    // report any errors if they have occured when parsing the program aguments.
351    if (arguments.errors())
352    {
353        arguments.writeErrorMessages(std::cout);
354        return 1;
355    }
356   
357    if (arguments.argc()<=1)
358    {
359        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
360        return 1;
361    }
362
363
364    // any option left unread are converted into errors to write out later.
365    arguments.reportRemainingOptionsAsUnrecognized();
366
367    // report any errors if they have occured when parsing the program aguments.
368    if (arguments.errors())
369    {
370        arguments.writeErrorMessages(std::cout);
371    }
372/*
373    // set up a post swap callback to flush deleted GL objects and compile new GL objects           
374    for(unsigned int cameraNum=0;cameraNum<viewer.getNumberOfCameras();++cameraNum)
375    {
376        Producer::Camera* camera=viewer.getCamera(cameraNum);
377        camera->addPostSwapCallback(new PostSwapFinishCallback());
378    }
379*/
380    // set the scene to render
381    viewer.setSceneData(geode.get());
382
383    // create the windows and run the threads.
384    viewer.realize();
385
386    while( !viewer.done() )
387    {
388        // wait for all cull and draw threads to complete.
389        viewer.sync();
390       
391        // update the scene by traversing it with the the update visitor which will
392        // call all node update callbacks and animations.
393        viewer.update();
394         
395        // fire off the cull and draw traversals of the scene.
396        viewer.frame();
397       
398    }
399   
400    // wait for all cull and draw threads to complete before exit.
401    viewer.sync();
402
403    return 0;
404
405
406}
Note: See TracBrowser for help on using the browser.