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

Revision 3825, 9.7 kB (checked in by robert, 10 years ago)

Changed the mpeg plugin to read movies the original way up rather than the
OpenGL way up to keep them consistent with the xine and quicktime movie codes

  • 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)
182{
183    bool useTextureRectangle = true;
184    if (useTextureRectangle)
185    {
186        osg::Geometry* pictureQuad = createTexturedQuadGeometry(pos,
187                                           osg::Vec3(width,0.0f,0.0f),
188                                           osg::Vec3(0.0f,0.0f,height),
189                                           0.0f,image->t(), image->s(),0.0f);
190                                       
191        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
192                    new osg::TextureRectangle(image),
193                    osg::StateAttribute::ON);
194                   
195        return pictureQuad;
196    }
197    else
198    {
199        osg::Geometry* pictureQuad = createTexturedQuadGeometry(pos,
200                                           osg::Vec3(width,0.0f,0.0f),
201                                           osg::Vec3(0.0f,0.0f,height),
202                                           0.0f,0.0f, 1.0f,1.0f);
203                                       
204        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
205                    new osg::Texture2D(image),
206                    osg::StateAttribute::ON);
207
208        return pictureQuad;
209    }
210}
211
212int main(int argc, char** argv)
213{
214    // use an ArgumentParser object to manage the program arguments.
215    osg::ArgumentParser arguments(&argc,argv);
216   
217    // set up the usage document, in case we need to print out how to use this program.
218    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
219    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
220    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
221    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
222   
223
224    // construct the viewer.
225    osgProducer::Viewer viewer(arguments);
226
227    // set up the value with sensible default event handlers.
228    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
229
230    // register the handler to add keyboard and mosue handling.
231    MovieEventHandler* meh = new MovieEventHandler();
232    viewer.getEventHandlerList().push_front(meh);
233
234
235    // get details on keyboard and mouse bindings used by the viewer.
236    viewer.getUsage(*arguments.getApplicationUsage());
237
238    // if user request help write it out to cout.
239    if (arguments.read("-h") || arguments.read("--help"))
240    {
241        arguments.getApplicationUsage()->write(std::cout);
242        return 1;
243    }
244
245    osg::Geode* geode = new osg::Geode;
246    osg::Vec3 pos(0.0f,0.0f,0.0f);
247   
248    for(int i=1;i<arguments.argc();++i)
249    {
250        if (arguments.isString(i))
251        {
252            osg::Image* image = osgDB::readImageFile(arguments[i]);
253            geode->addDrawable(createTexturedQuadGeometry(pos,image->s(),image->t(),image));
254            geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
255           
256            pos.z() += image->t()*1.5f;
257        }
258
259    }
260
261    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
262    meh->set(geode);
263
264    // report any errors if they have occured when parsing the program aguments.
265    if (arguments.errors())
266    {
267        arguments.writeErrorMessages(std::cout);
268        return 1;
269    }
270   
271    if (arguments.argc()<=1)
272    {
273        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
274        return 1;
275    }
276
277
278    // any option left unread are converted into errors to write out later.
279    arguments.reportRemainingOptionsAsUnrecognized();
280
281    // report any errors if they have occured when parsing the program aguments.
282    if (arguments.errors())
283    {
284        arguments.writeErrorMessages(std::cout);
285    }
286
287    // set up a post swap callback to flush deleted GL objects and compile new GL objects           
288    for(unsigned int cameraNum=0;cameraNum<viewer.getNumberOfCameras();++cameraNum)
289    {
290        Producer::Camera* camera=viewer.getCamera(cameraNum);
291        camera->addPostSwapCallback(new PostSwapFinishCallback());
292    }
293
294    // set the scene to render
295    viewer.setSceneData(geode);
296
297    // create the windows and run the threads.
298    viewer.realize();
299
300    while( !viewer.done() )
301    {
302        // wait for all cull and draw threads to complete.
303        viewer.sync();
304       
305        // update the scene by traversing it with the the update visitor which will
306        // call all node update callbacks and animations.
307        viewer.update();
308         
309        // fire off the cull and draw traversals of the scene.
310        viewer.frame();
311       
312    }
313   
314    // wait for all cull and draw threads to complete before exit.
315    viewer.sync();
316
317    return 0;
318
319
320}
Note: See TracBrowser for help on using the browser.