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

Revision 4323, 11.9 kB (checked in by robert, 10 years ago)

Added \n to end of a couple shader source lines.

  • 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                return true;
159            }
160            else if (ea.getKey()=='l')
161            {
162                return true;
163            }
164            return false;
165        }
166
167        default:
168            return false;
169    }
170}
171
172void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
173{
174    usage.addKeyboardMouseBinding("p","Pause movie");
175    usage.addKeyboardMouseBinding("s","Play movie");
176    usage.addKeyboardMouseBinding("r","Start movie");
177    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
178}
179
180
181osg::Geometry* createTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image, bool useTextureRectangle)
182{
183    if (useTextureRectangle)
184    {
185        osg::Geometry* pictureQuad = createTexturedQuadGeometry(pos,
186                                           osg::Vec3(width,0.0f,0.0f),
187                                           osg::Vec3(0.0f,0.0f,height),
188                                           0.0f,image->t(), image->s(),0.0f);
189
190        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
191                    new osg::TextureRectangle(image),
192                    osg::StateAttribute::ON);
193                   
194        return pictureQuad;
195    }
196    else
197    {
198        osg::Geometry* pictureQuad = createTexturedQuadGeometry(pos,
199                                           osg::Vec3(width,0.0f,0.0f),
200                                           osg::Vec3(0.0f,0.0f,height),
201                                           0.0f,1.0f, 1.0f,0.0f);
202                                   
203        osg::Texture2D* texture = new osg::Texture2D(image);
204        texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); 
205                                       
206        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
207                    texture,
208                    osg::StateAttribute::ON);
209
210        return pictureQuad;
211    }
212}
213
214int main(int argc, char** argv)
215{
216    // use an ArgumentParser object to manage the program arguments.
217    osg::ArgumentParser arguments(&argc,argv);
218   
219    // set up the usage document, in case we need to print out how to use this program.
220    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
221    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
222    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
223    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
224   
225    bool useTextureRectangle = true;
226    bool useShader = false;
227
228    // construct the viewer.
229    osgProducer::Viewer viewer(arguments);
230   
231    while (arguments.read("--texture2D")) useTextureRectangle=false;
232    while (arguments.read("--shader")) useShader=true;
233
234    // set up the value with sensible default event handlers.
235    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
236
237    // register the handler to add keyboard and mosue handling.
238    MovieEventHandler* meh = new MovieEventHandler();
239    viewer.getEventHandlerList().push_front(meh);
240
241
242    // get details on keyboard and mouse bindings used by the viewer.
243    viewer.getUsage(*arguments.getApplicationUsage());
244
245    // if user request help write it out to cout.
246    if (arguments.read("-h") || arguments.read("--help"))
247    {
248        arguments.getApplicationUsage()->write(std::cout);
249        return 1;
250    }
251
252    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
253    osg::Vec3 pos(0.0f,0.0f,0.0f);
254       
255    osg::StateSet* stateset = geode->getOrCreateStateSet();
256    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
257
258    if (useShader)
259    {
260        //useTextureRectangle = false;
261       
262        static const char *shaderSourceTextureRec = {
263            "uniform vec4 cutoff_color;\n"
264            "uniform samplerRect movie_texture;\n"
265            "void main(void)\n"
266            "{\n"
267            "    vec4 texture_color = textureRect(movie_texture, gl_TexCoord[0]); \n"
268            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
269            "    gl_FragColor = texture_color;\n"
270            "}\n"
271        };
272
273        static const char *shaderSourceTexture2D = {
274            "uniform vec4 cutoff_color;\n"
275            "uniform sampler2D movie_texture;\n"
276            "void main(void)\n"
277            "{\n"
278            "    vec4 texture_color = texture2D(movie_texture, gl_TexCoord[0]); \n"
279            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
280            "    gl_FragColor = texture_color;\n"
281            "}\n"
282        };
283
284        osg::Program* program = new osg::Program;
285       
286        program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
287                                           useTextureRectangle ? shaderSourceTextureRec : shaderSourceTexture2D));
288
289        stateset->addUniform(new osg::Uniform("cutoff_color",osg::Vec4(0.1f,0.1f,0.1f,1.0f)));
290        stateset->addUniform(new osg::Uniform("movie_texture",0));
291
292        stateset->setAttribute(program);
293
294    }
295
296
297    for(int i=1;i<arguments.argc();++i)
298    {
299        if (arguments.isString(i))
300        {
301            osg::Image* image = osgDB::readImageFile(arguments[i]);
302            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
303            if (imagestream) imagestream->play();
304           
305            if (image)
306            {
307                geode->addDrawable(createTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle));
308               
309                pos.z() += image->t()*1.5f;
310            }
311            else
312            {
313                std::cout<<"Unable to read file "<<arguments[i]<<std::endl;
314            }           
315        }
316    }
317   
318    if (geode->getNumDrawables()==0)
319    {
320        // nothing loaded.
321        return 1;
322    }
323
324    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
325    meh->set(geode.get());
326
327    // report any errors if they have occured when parsing the program aguments.
328    if (arguments.errors())
329    {
330        arguments.writeErrorMessages(std::cout);
331        return 1;
332    }
333   
334    if (arguments.argc()<=1)
335    {
336        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
337        return 1;
338    }
339
340
341    // any option left unread are converted into errors to write out later.
342    arguments.reportRemainingOptionsAsUnrecognized();
343
344    // report any errors if they have occured when parsing the program aguments.
345    if (arguments.errors())
346    {
347        arguments.writeErrorMessages(std::cout);
348    }
349/*
350    // set up a post swap callback to flush deleted GL objects and compile new GL objects           
351    for(unsigned int cameraNum=0;cameraNum<viewer.getNumberOfCameras();++cameraNum)
352    {
353        Producer::Camera* camera=viewer.getCamera(cameraNum);
354        camera->addPostSwapCallback(new PostSwapFinishCallback());
355    }
356*/
357    // set the scene to render
358    viewer.setSceneData(geode.get());
359
360    // create the windows and run the threads.
361    viewer.realize();
362
363    while( !viewer.done() )
364    {
365        // wait for all cull and draw threads to complete.
366        viewer.sync();
367       
368        // update the scene by traversing it with the the update visitor which will
369        // call all node update callbacks and animations.
370        viewer.update();
371         
372        // fire off the cull and draw traversals of the scene.
373        viewer.frame();
374       
375    }
376   
377    // wait for all cull and draw threads to complete before exit.
378    viewer.sync();
379
380    return 0;
381
382
383}
Note: See TracBrowser for help on using the browser.