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

Revision 4321, 11.3 kB (checked in by robert, 9 years ago)

Added experiment GLSL fragment shader to clip out dark areas of videos.

  • 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 *shaderSource = {
263            "uniform vec4 cutoff_color;\n"
264            "uniform samplerRect movie_texture;"
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        osg::Program* program = new osg::Program;
273        program->addShader(new osg::Shader(osg::Shader::FRAGMENT,shaderSource));
274
275        stateset->addUniform(new osg::Uniform("cutoff_color",osg::Vec4(0.1f,0.1f,0.1f,1.0f)));
276        stateset->addUniform(new osg::Uniform("movie_texture",0));
277
278        stateset->setAttribute(program);
279
280    }
281
282
283    for(int i=1;i<arguments.argc();++i)
284    {
285        if (arguments.isString(i))
286        {
287            osg::Image* image = osgDB::readImageFile(arguments[i]);
288            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
289            if (imagestream) imagestream->play();
290           
291            if (image)
292            {
293                geode->addDrawable(createTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle));
294               
295                pos.z() += image->t()*1.5f;
296            }
297            else
298            {
299                std::cout<<"Unable to read file "<<arguments[i]<<std::endl;
300            }           
301        }
302    }
303   
304    if (geode->getNumDrawables()==0)
305    {
306        // nothing loaded.
307        return 1;
308    }
309
310    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
311    meh->set(geode.get());
312
313    // report any errors if they have occured when parsing the program aguments.
314    if (arguments.errors())
315    {
316        arguments.writeErrorMessages(std::cout);
317        return 1;
318    }
319   
320    if (arguments.argc()<=1)
321    {
322        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
323        return 1;
324    }
325
326
327    // any option left unread are converted into errors to write out later.
328    arguments.reportRemainingOptionsAsUnrecognized();
329
330    // report any errors if they have occured when parsing the program aguments.
331    if (arguments.errors())
332    {
333        arguments.writeErrorMessages(std::cout);
334    }
335/*
336    // set up a post swap callback to flush deleted GL objects and compile new GL objects           
337    for(unsigned int cameraNum=0;cameraNum<viewer.getNumberOfCameras();++cameraNum)
338    {
339        Producer::Camera* camera=viewer.getCamera(cameraNum);
340        camera->addPostSwapCallback(new PostSwapFinishCallback());
341    }
342*/
343    // set the scene to render
344    viewer.setSceneData(geode.get());
345
346    // create the windows and run the threads.
347    viewer.realize();
348
349    while( !viewer.done() )
350    {
351        // wait for all cull and draw threads to complete.
352        viewer.sync();
353       
354        // update the scene by traversing it with the the update visitor which will
355        // call all node update callbacks and animations.
356        viewer.update();
357         
358        // fire off the cull and draw traversals of the scene.
359        viewer.frame();
360       
361    }
362   
363    // wait for all cull and draw threads to complete before exit.
364    viewer.sync();
365
366    return 0;
367
368
369}
Note: See TracBrowser for help on using the browser.