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

Revision 5927, 15.2 kB (checked in by robert, 8 years ago)

Ported following examples to osgViewer:

osggeodemo
osggeometry
osghud
osgimpostor
osgkeyboard
osglauncher
osglight
osglightpoint
osglogicop
osglogo
osgmovie
osgmultiplecameras
osgmultitexture
osgoccluder
osgparametric
osgparticle

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// -*-c++-*-
2
3#include <osgViewer/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
21#include <iostream>
22
23osg::ImageStream* s_imageStream = 0;
24class MovieEventHandler : public osgGA::GUIEventHandler
25{
26public:
27
28    MovieEventHandler() {}
29   
30    void set(osg::Node* node);
31
32    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
33   
34    virtual void getUsage(osg::ApplicationUsage& usage) const;
35
36    typedef std::vector< osg::ref_ptr<osg::ImageStream> > ImageStreamList;
37
38protected:
39
40    virtual ~MovieEventHandler() {}
41
42    class FindImageStreamsVisitor : public osg::NodeVisitor
43    {
44    public:
45        FindImageStreamsVisitor(ImageStreamList& imageStreamList):
46            _imageStreamList(imageStreamList) {}
47           
48        virtual void apply(osg::Geode& geode)
49        {
50            apply(geode.getStateSet());
51
52            for(unsigned int i=0;i<geode.getNumDrawables();++i)
53            {
54                apply(geode.getDrawable(i)->getStateSet());
55            }
56       
57            traverse(geode);
58        }
59
60        virtual void apply(osg::Node& node)
61        {
62            apply(node.getStateSet());
63            traverse(node);
64        }
65       
66        inline void apply(osg::StateSet* stateset)
67        {
68            if (!stateset) return;
69           
70            osg::StateAttribute* attr = stateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
71            if (attr)
72            {
73                osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(attr);
74                if (texture2D) apply(dynamic_cast<osg::ImageStream*>(texture2D->getImage()));
75
76                osg::TextureRectangle* textureRec = dynamic_cast<osg::TextureRectangle*>(attr);
77                if (textureRec) apply(dynamic_cast<osg::ImageStream*>(textureRec->getImage()));
78            }
79        }
80       
81        inline void apply(osg::ImageStream* imagestream)
82        {
83            if (imagestream)
84            {
85                _imageStreamList.push_back(imagestream);
86                s_imageStream = imagestream;
87            }
88        }
89       
90        ImageStreamList& _imageStreamList;
91    };
92
93
94    ImageStreamList _imageStreamList;
95   
96};
97
98
99
100void MovieEventHandler::set(osg::Node* node)
101{
102    _imageStreamList.clear();
103    if (node)
104    {
105        FindImageStreamsVisitor fisv(_imageStreamList);
106        node->accept(fisv);
107    }
108}
109
110
111bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
112{
113    switch(ea.getEventType())
114    {
115        case(osgGA::GUIEventAdapter::MOVE):
116        case(osgGA::GUIEventAdapter::PUSH):
117        case(osgGA::GUIEventAdapter::RELEASE):
118        {
119#if 0
120            osgProducer::Viewer* viewer = dynamic_cast<osgProducer::Viewer*>(&aa);
121            osgUtil::IntersectVisitor::HitList hlist;
122            if (viewer->computeIntersections(ea.getX(),ea.getY(), nv->getNodePath().back(), hlist))
123            {
124                if (!hlist.empty())
125                {
126                    // use the nearest intersection                 
127                    osgUtil::Hit& hit = hlist.front();
128                    osg::Drawable* drawable = hit.getDrawable();
129                    osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0;
130                    osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
131
132                    if (vertices)
133                    {
134                        // get the vertex indices.
135                        const osgUtil::Hit::VecIndexList& vil = hit.getVecIndexList();
136                       
137                        if (vil.size()==3)
138                        {
139
140                            int i1 = vil[0];
141                            int i2 = vil[1];
142                            int i3 = vil[2];
143                            osg::Vec3 v1 = (*vertices)[i1];
144                            osg::Vec3 v2 = (*vertices)[i2];
145                            osg::Vec3 v3 = (*vertices)[i3];
146                            osg::Vec3 v = hit.getLocalIntersectPoint();
147                            osg::Vec3 p1 = hit.getLocalLineSegment()->start();
148                            osg::Vec3 p2 = hit.getLocalLineSegment()->end();
149                           
150                            osg::Vec3 p12 = p1-p2;
151                            osg::Vec3 v13 = v1-v3;
152                            osg::Vec3 v23 = v2-v3;
153                            osg::Vec3 p1v3 = p1-v3;
154                           
155                            osg::Matrix matrix(p12.x(), v13.x(), v23.x(), 0.0,
156                                               p12.y(), v13.y(), v23.y(), 0.0,
157                                               p12.z(), v13.z(), v23.z(), 0.0,
158                                               0.0,    0.0,    0.0,    1.0);
159                                               
160                            osg::Matrix inverse;
161                            inverse.invert(matrix);
162                           
163                            osg::Vec3 ratio = inverse*p1v3;
164
165                            // extract the baricentric coordinates.                           
166                            float r1 = ratio.y();
167                            float r2 = ratio.z();
168                            float r3 = 1.0f-r1-r2;
169
170                            osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
171                            osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
172                            if (texcoords_Vec2Array)
173                            {
174                                // we have tex coord array so now we can compute the final tex coord at the point of intersection.                               
175                                osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1];
176                                osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2];
177                                osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3];
178                                osg::Vec2 tc = tc1*r1 + tc2*r2 + tc3*r3;
179                               
180                                osg::notify(osg::NOTICE)<<"We hit tex coords "<<tc<<std::endl;
181                               
182                            }
183                           
184                           
185                        }
186                        else
187                        {
188                            osg::notify(osg::NOTICE)<<"Hit but insufficient indices to work with";
189                        }
190   
191                    }
192                }
193            }
194            else
195            {
196                osg::notify(osg::NOTICE)<<"No hit"<<std::endl;
197            }
198#else
199            osg::notify(osg::NOTICE)<<"Need to implement picking."<<std::endl;
200#endif
201            break;
202        }
203        case(osgGA::GUIEventAdapter::KEYDOWN):
204        {
205            if (ea.getKey()=='s')
206            {
207                for(ImageStreamList::iterator itr=_imageStreamList.begin();
208                    itr!=_imageStreamList.end();
209                    ++itr)
210                {
211                    std::cout<<"Play"<<std::endl;
212                     (*itr)->play();
213                }
214                return true;
215            }
216            else if (ea.getKey()=='p')
217            {
218                for(ImageStreamList::iterator itr=_imageStreamList.begin();
219                    itr!=_imageStreamList.end();
220                    ++itr)
221                {
222                    std::cout<<"Pause"<<std::endl;
223                    (*itr)->pause();
224                }
225                return true;
226            }
227            else if (ea.getKey()=='r')
228            {
229                for(ImageStreamList::iterator itr=_imageStreamList.begin();
230                    itr!=_imageStreamList.end();
231                    ++itr)
232                {
233                    std::cout<<"Restart"<<std::endl;
234                    (*itr)->rewind();
235                    (*itr)->play();
236                }
237                return true;
238            }
239            else if (ea.getKey()=='l')
240            {
241                for(ImageStreamList::iterator itr=_imageStreamList.begin();
242                    itr!=_imageStreamList.end();
243                    ++itr)
244                {
245                    if ( (*itr)->getLoopingMode() == osg::ImageStream::LOOPING)
246                    {
247                        std::cout<<"Toggle Looping Off"<<std::endl;
248                        (*itr)->setLoopingMode( osg::ImageStream::NO_LOOPING );
249                    }
250                    else
251                    {
252                        std::cout<<"Toggle Looping On"<<std::endl;
253                        (*itr)->setLoopingMode( osg::ImageStream::LOOPING );
254                    }
255                }
256                return true;
257            }
258            return false;
259        }
260
261        default:
262            return false;
263    }
264    return false;
265}
266
267void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
268{
269    usage.addKeyboardMouseBinding("p","Pause movie");
270    usage.addKeyboardMouseBinding("s","Play movie");
271    usage.addKeyboardMouseBinding("r","Restart movie");
272    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
273}
274
275
276osg::Geometry* myCreateTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image, bool useTextureRectangle)
277{
278    if (useTextureRectangle)
279    {
280        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
281                                           osg::Vec3(width,0.0f,0.0f),
282                                           osg::Vec3(0.0f,0.0f,height),
283                                           0.0f,image->t(), image->s(),0.0f);
284
285        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
286                    new osg::TextureRectangle(image),
287                    osg::StateAttribute::ON);
288                   
289        return pictureQuad;
290    }
291    else
292    {
293        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
294                                           osg::Vec3(width,0.0f,0.0f),
295                                           osg::Vec3(0.0f,0.0f,height),
296                                           0.0f,1.0f, 1.0f,0.0f);
297                                   
298        osg::Texture2D* texture = new osg::Texture2D(image);
299        texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); 
300                                       
301        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
302                    texture,
303                    osg::StateAttribute::ON);
304
305        return pictureQuad;
306    }
307}
308
309int main(int argc, char** argv)
310{
311    // use an ArgumentParser object to manage the program arguments.
312    osg::ArgumentParser arguments(&argc,argv);
313   
314    // set up the usage document, in case we need to print out how to use this program.
315    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
316    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" example demonstrates the use of ImageStream for rendering movies as textures.");
317    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
318    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
319    arguments.getApplicationUsage()->addCommandLineOption("--texture2D","Use Texture2D rather than TextureRectangle.");
320    arguments.getApplicationUsage()->addCommandLineOption("--shader","Use shaders to post process the video.");
321   
322    bool useTextureRectangle = true;
323    bool useShader = false;
324
325    // construct the viewer.
326    osgViewer::Viewer viewer;
327   
328    while (arguments.read("--texture2D")) useTextureRectangle=false;
329    while (arguments.read("--shader")) useShader=true;
330
331    // if user request help write it out to cout.
332    if (arguments.read("-h") || arguments.read("--help"))
333    {
334        arguments.getApplicationUsage()->write(std::cout);
335        return 1;
336    }
337
338    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
339    osg::Vec3 pos(0.0f,0.0f,0.0f);
340       
341    osg::StateSet* stateset = geode->getOrCreateStateSet();
342    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
343
344    if (useShader)
345    {
346        //useTextureRectangle = false;
347       
348        static const char *shaderSourceTextureRec = {
349            "uniform vec4 cutoff_color;\n"
350            "uniform samplerRect movie_texture;\n"
351            "void main(void)\n"
352            "{\n"
353            "    vec4 texture_color = textureRect(movie_texture, gl_TexCoord[0]); \n"
354            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
355            "    gl_FragColor = texture_color;\n"
356            "}\n"
357        };
358
359        static const char *shaderSourceTexture2D = {
360            "uniform vec4 cutoff_color;\n"
361            "uniform sampler2D movie_texture;\n"
362            "void main(void)\n"
363            "{\n"
364            "    vec4 texture_color = texture2D(movie_texture, gl_TexCoord[0]); \n"
365            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
366            "    gl_FragColor = texture_color;\n"
367            "}\n"
368        };
369
370        osg::Program* program = new osg::Program;
371       
372        program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
373                                           useTextureRectangle ? shaderSourceTextureRec : shaderSourceTexture2D));
374
375        stateset->addUniform(new osg::Uniform("cutoff_color",osg::Vec4(0.1f,0.1f,0.1f,1.0f)));
376        stateset->addUniform(new osg::Uniform("movie_texture",0));
377
378        stateset->setAttribute(program);
379
380    }
381
382
383    for(int i=1;i<arguments.argc();++i)
384    {
385        if (arguments.isString(i))
386        {
387            osg::Image* image = osgDB::readImageFile(arguments[i]);
388            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
389            if (imagestream) imagestream->play();
390           
391            if (image)
392            {
393                geode->addDrawable(myCreateTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle));
394               
395                pos.z() += image->t()*1.5f;
396            }
397            else
398            {
399                std::cout<<"Unable to read file "<<arguments[i]<<std::endl;
400            }           
401        }
402    }
403   
404    if (geode->getNumDrawables()==0)
405    {
406        // nothing loaded.
407        arguments.getApplicationUsage()->write(std::cout);
408        return 1;
409    }
410
411    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
412    MovieEventHandler* meh = new MovieEventHandler();
413    geode->setEventCallback(meh);
414    meh->set(geode.get());
415
416    // report any errors if they have occured when parsing the program aguments.
417    if (arguments.errors())
418    {
419        arguments.writeErrorMessages(std::cout);
420        return 1;
421    }
422   
423    if (arguments.argc()<=1)
424    {
425        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
426        return 1;
427    }
428
429    // set the scene to render
430    viewer.setSceneData(geode.get());
431
432    // create the windows and run the threads.
433    return viewer.run();
434
435
436}
Note: See TracBrowser for help on using the browser.