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

Revision 5636, 17.1 kB (checked in by robert, 8 years ago)

Removed deprecated GUIEventHandler method

  • 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#include <osg/io_utils>
17
18#include <osgGA/TrackballManipulator>
19#include <osgGA/EventVisitor>
20
21osg::ImageStream* s_imageStream = 0;
22class PostSwapFinishCallback : public Producer::Camera::Callback
23{
24public:
25
26    PostSwapFinishCallback() {}
27
28    virtual void operator()(const Producer::Camera& camera)
29    {
30        // osg::Timer_t start_tick = osg::Timer::instance()->tick();
31       
32        osgProducer::OsgSceneHandler* sh = const_cast<osgProducer::OsgSceneHandler*>(dynamic_cast<const osgProducer::OsgSceneHandler*>(camera.getSceneHandler()));
33   
34        if (s_imageStream && s_imageStream->getPixelBufferObject()) s_imageStream->getPixelBufferObject()->compileBuffer(*(sh->getSceneView()->getState()));
35        // glFinish();
36
37        //osg::notify(osg::NOTICE)<<"callback after PBO "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
38    }
39};
40
41class MovieEventHandler : public osgGA::GUIEventHandler
42{
43public:
44
45    MovieEventHandler() {}
46   
47    void set(osg::Node* node);
48
49    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
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& aa, osg::Object*, osg::NodeVisitor* nv)
129{
130    switch(ea.getEventType())
131    {
132        case(osgGA::GUIEventAdapter::MOVE):
133        case(osgGA::GUIEventAdapter::PUSH):
134        case(osgGA::GUIEventAdapter::RELEASE):
135        {
136            osgProducer::Viewer* viewer = dynamic_cast<osgProducer::Viewer*>(&aa);
137            osgUtil::IntersectVisitor::HitList hlist;
138            if (viewer->computeIntersections(ea.getX(),ea.getY(), nv->getNodePath().back(), hlist))
139            {
140                if (!hlist.empty())
141                {
142                    // use the nearest intersection                 
143                    osgUtil::Hit& hit = hlist.front();
144                    osg::Drawable* drawable = hit.getDrawable();
145                    osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0;
146                    osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
147
148                    if (vertices)
149                    {
150                        // get the vertex indices.
151                        const osgUtil::Hit::VecIndexList& vil = hit.getVecIndexList();
152                       
153                        if (vil.size()==3)
154                        {
155
156                            int i1 = vil[0];
157                            int i2 = vil[1];
158                            int i3 = vil[2];
159                            osg::Vec3 v1 = (*vertices)[i1];
160                            osg::Vec3 v2 = (*vertices)[i2];
161                            osg::Vec3 v3 = (*vertices)[i3];
162                            osg::Vec3 v = hit.getLocalIntersectPoint();
163                            osg::Vec3 p1 = hit.getLocalLineSegment()->start();
164                            osg::Vec3 p2 = hit.getLocalLineSegment()->end();
165                           
166                            osg::Vec3 p12 = p1-p2;
167                            osg::Vec3 v13 = v1-v3;
168                            osg::Vec3 v23 = v2-v3;
169                            osg::Vec3 p1v3 = p1-v3;
170                           
171                            osg::Matrix matrix(p12.x(), v13.x(), v23.x(), 0.0,
172                                               p12.y(), v13.y(), v23.y(), 0.0,
173                                               p12.z(), v13.z(), v23.z(), 0.0,
174                                               0.0,    0.0,    0.0,    1.0);
175                                               
176                            osg::Matrix inverse;
177                            inverse.invert(matrix);
178                           
179                            osg::Vec3 ratio = inverse*p1v3;
180
181                            // extract the baricentric coordinates.                           
182                            float r1 = ratio.y();
183                            float r2 = ratio.z();
184                            float r3 = 1.0f-r1-r2;
185
186                            osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
187                            osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
188                            if (texcoords_Vec2Array)
189                            {
190                                // we have tex coord array so now we can compute the final tex coord at the point of intersection.                               
191                                osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1];
192                                osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2];
193                                osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3];
194                                osg::Vec2 tc = tc1*r1 + tc2*r2 + tc3*r3;
195                               
196                                osg::notify(osg::NOTICE)<<"We hit tex coords "<<tc<<std::endl;
197                               
198                            }
199                           
200                           
201                        }
202                        else
203                        {
204                            osg::notify(osg::NOTICE)<<"Hit but insufficient indices to work with";
205                        }
206   
207                    }
208
209                }
210            }
211            else
212            {
213                osg::notify(osg::NOTICE)<<"No hit"<<std::endl;
214            }
215            break;
216        }
217        case(osgGA::GUIEventAdapter::KEYDOWN):
218        {
219            if (ea.getKey()=='s')
220            {
221                for(ImageStreamList::iterator itr=_imageStreamList.begin();
222                    itr!=_imageStreamList.end();
223                    ++itr)
224                {
225                    std::cout<<"Play"<<std::endl;
226                     (*itr)->play();
227                }
228                return true;
229            }
230            else if (ea.getKey()=='p')
231            {
232                for(ImageStreamList::iterator itr=_imageStreamList.begin();
233                    itr!=_imageStreamList.end();
234                    ++itr)
235                {
236                    std::cout<<"Pause"<<std::endl;
237                    (*itr)->pause();
238                }
239                return true;
240            }
241            else if (ea.getKey()=='r')
242            {
243                for(ImageStreamList::iterator itr=_imageStreamList.begin();
244                    itr!=_imageStreamList.end();
245                    ++itr)
246                {
247                    std::cout<<"Restart"<<std::endl;
248                    (*itr)->rewind();
249                    (*itr)->play();
250                }
251                return true;
252            }
253            else if (ea.getKey()=='l')
254            {
255                for(ImageStreamList::iterator itr=_imageStreamList.begin();
256                    itr!=_imageStreamList.end();
257                    ++itr)
258                {
259                    if ( (*itr)->getLoopingMode() == osg::ImageStream::LOOPING)
260                    {
261                        std::cout<<"Toggle Looping Off"<<std::endl;
262                        (*itr)->setLoopingMode( osg::ImageStream::NO_LOOPING );
263                    }
264                    else
265                    {
266                        std::cout<<"Toggle Looping On"<<std::endl;
267                        (*itr)->setLoopingMode( osg::ImageStream::LOOPING );
268                    }
269                }
270                return true;
271            }
272            return false;
273        }
274
275        default:
276            return false;
277    }
278    return false;
279}
280
281void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
282{
283    usage.addKeyboardMouseBinding("p","Pause movie");
284    usage.addKeyboardMouseBinding("s","Play movie");
285    usage.addKeyboardMouseBinding("r","Restart movie");
286    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
287}
288
289
290osg::Geometry* myCreateTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image, bool useTextureRectangle)
291{
292    if (useTextureRectangle)
293    {
294        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
295                                           osg::Vec3(width,0.0f,0.0f),
296                                           osg::Vec3(0.0f,0.0f,height),
297                                           0.0f,image->t(), image->s(),0.0f);
298
299        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
300                    new osg::TextureRectangle(image),
301                    osg::StateAttribute::ON);
302                   
303        return pictureQuad;
304    }
305    else
306    {
307        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
308                                           osg::Vec3(width,0.0f,0.0f),
309                                           osg::Vec3(0.0f,0.0f,height),
310                                           0.0f,1.0f, 1.0f,0.0f);
311                                   
312        osg::Texture2D* texture = new osg::Texture2D(image);
313        texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); 
314                                       
315        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
316                    texture,
317                    osg::StateAttribute::ON);
318
319        return pictureQuad;
320    }
321}
322
323int main(int argc, char** argv)
324{
325    // use an ArgumentParser object to manage the program arguments.
326    osg::ArgumentParser arguments(&argc,argv);
327   
328    // set up the usage document, in case we need to print out how to use this program.
329    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
330    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" example demonstrates the use of ImageStream for rendering movies as textures.");
331    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
332    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
333   
334    bool useTextureRectangle = true;
335    bool useShader = false;
336
337    // construct the viewer.
338    osgProducer::Viewer viewer(arguments);
339   
340    while (arguments.read("--texture2D")) useTextureRectangle=false;
341    while (arguments.read("--shader")) useShader=true;
342
343    // set up the value with sensible default event handlers.
344    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
345
346    // get details on keyboard and mouse bindings used by the viewer.
347    viewer.getUsage(*arguments.getApplicationUsage());
348
349    // if user request help write it out to cout.
350    if (arguments.read("-h") || arguments.read("--help"))
351    {
352        arguments.getApplicationUsage()->write(std::cout);
353        return 1;
354    }
355
356    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
357    osg::Vec3 pos(0.0f,0.0f,0.0f);
358       
359    osg::StateSet* stateset = geode->getOrCreateStateSet();
360    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
361
362    if (useShader)
363    {
364        //useTextureRectangle = false;
365       
366        static const char *shaderSourceTextureRec = {
367            "uniform vec4 cutoff_color;\n"
368            "uniform samplerRect movie_texture;\n"
369            "void main(void)\n"
370            "{\n"
371            "    vec4 texture_color = textureRect(movie_texture, gl_TexCoord[0]); \n"
372            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
373            "    gl_FragColor = texture_color;\n"
374            "}\n"
375        };
376
377        static const char *shaderSourceTexture2D = {
378            "uniform vec4 cutoff_color;\n"
379            "uniform sampler2D movie_texture;\n"
380            "void main(void)\n"
381            "{\n"
382            "    vec4 texture_color = texture2D(movie_texture, gl_TexCoord[0]); \n"
383            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
384            "    gl_FragColor = texture_color;\n"
385            "}\n"
386        };
387
388        osg::Program* program = new osg::Program;
389       
390        program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
391                                           useTextureRectangle ? shaderSourceTextureRec : shaderSourceTexture2D));
392
393        stateset->addUniform(new osg::Uniform("cutoff_color",osg::Vec4(0.1f,0.1f,0.1f,1.0f)));
394        stateset->addUniform(new osg::Uniform("movie_texture",0));
395
396        stateset->setAttribute(program);
397
398    }
399
400
401    for(int i=1;i<arguments.argc();++i)
402    {
403        if (arguments.isString(i))
404        {
405            osg::Image* image = osgDB::readImageFile(arguments[i]);
406            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
407            if (imagestream) imagestream->play();
408           
409            if (image)
410            {
411                geode->addDrawable(myCreateTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle));
412               
413                pos.z() += image->t()*1.5f;
414            }
415            else
416            {
417                std::cout<<"Unable to read file "<<arguments[i]<<std::endl;
418            }           
419        }
420    }
421   
422    if (geode->getNumDrawables()==0)
423    {
424        // nothing loaded.
425        return 1;
426    }
427   
428   
429
430    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
431    MovieEventHandler* meh = new MovieEventHandler();
432    geode->setEventCallback(meh);
433    meh->set(geode.get());
434
435    // report any errors if they have occured when parsing the program aguments.
436    if (arguments.errors())
437    {
438        arguments.writeErrorMessages(std::cout);
439        return 1;
440    }
441   
442    if (arguments.argc()<=1)
443    {
444        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
445        return 1;
446    }
447
448
449    // any option left unread are converted into errors to write out later.
450    arguments.reportRemainingOptionsAsUnrecognized();
451
452    // report any errors if they have occured when parsing the program aguments.
453    if (arguments.errors())
454    {
455        arguments.writeErrorMessages(std::cout);
456    }
457/*
458    // set up a post swap callback to flush deleted GL objects and compile new GL objects           
459    for(unsigned int cameraNum=0;cameraNum<viewer.getNumberOfCameras();++cameraNum)
460    {
461        Producer::Camera* camera=viewer.getCamera(cameraNum);
462        camera->addPostSwapCallback(new PostSwapFinishCallback());
463    }
464*/
465    // set the scene to render
466    viewer.setSceneData(geode.get());
467
468    // create the windows and run the threads.
469    viewer.realize();
470
471    while( !viewer.done() )
472    {
473        // wait for all cull and draw threads to complete.
474        viewer.sync();
475       
476        // update the scene by traversing it with the the update visitor which will
477        // call all node update callbacks and animations.
478        viewer.update();
479         
480        // fire off the cull and draw traversals of the scene.
481        viewer.frame();
482       
483    }
484   
485    // wait for all cull and draw threads to complete.
486    viewer.sync();
487
488    // run a clean up frame to delete all OpenGL objects.
489    viewer.cleanup_frame();
490
491    // wait for all the clean up frame to complete.
492    viewer.sync();
493
494    return 0;
495
496
497}
Note: See TracBrowser for help on using the browser.