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

Revision 10799, 24.2 kB (checked in by robert, 5 years ago)

From Cedric Pinson, "here an update of osgmovie example with the following features:
- play and pause now stop and play all streams given in the command line
(not only the first)
- add key + - to increase decrease the speed of all streams
- add key o to display all stream frame rate
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[6941]1/* OpenSceneGraph example, osgmovie.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
[2693]18
[5927]19#include <osgViewer/Viewer>
[6949]20#include <osgViewer/ViewerEventHandlers>
[2693]21
22#include <osgDB/ReadFile>
23
24#include <osg/Geode>
25#include <osg/Geometry>
26#include <osg/StateSet>
27#include <osg/Material>
28#include <osg/Texture2D>
29#include <osg/TextureRectangle>
[6624]30#include <osg/TextureCubeMap>
[2693]31#include <osg/TexMat>
32#include <osg/CullFace>
[2810]33#include <osg/ImageStream>
[4956]34#include <osg/io_utils>
[2693]35
36#include <osgGA/TrackballManipulator>
[7615]37#include <osgGA/StateSetManipulator>
[4956]38#include <osgGA/EventVisitor>
[2693]39
[5927]40#include <iostream>
[3819]41
[2810]42class MovieEventHandler : public osgGA::GUIEventHandler
43{
44public:
45
[10799]46    MovieEventHandler():_trackMouse(false) {}
[9705]47
[6624]48    void setMouseTracking(bool track) { _trackMouse = track; }
49    bool getMouseTracking() const { return _trackMouse; }
[9705]50
[2810]51    void set(osg::Node* node);
52
[4956]53    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
[9705]54
[2810]55    virtual void getUsage(osg::ApplicationUsage& usage) const;
56
[7648]57    typedef std::vector< osg::observer_ptr<osg::ImageStream> > ImageStreamList;
[2810]58
59protected:
60
61    virtual ~MovieEventHandler() {}
62
63    class FindImageStreamsVisitor : public osg::NodeVisitor
64    {
65    public:
66        FindImageStreamsVisitor(ImageStreamList& imageStreamList):
67            _imageStreamList(imageStreamList) {}
[9705]68
[2810]69        virtual void apply(osg::Geode& geode)
70        {
71            apply(geode.getStateSet());
72
73            for(unsigned int i=0;i<geode.getNumDrawables();++i)
74            {
75                apply(geode.getDrawable(i)->getStateSet());
76            }
[9705]77
[2810]78            traverse(geode);
79        }
80
81        virtual void apply(osg::Node& node)
82        {
83            apply(node.getStateSet());
84            traverse(node);
85        }
[9705]86
[2810]87        inline void apply(osg::StateSet* stateset)
88        {
89            if (!stateset) return;
[9705]90
[2810]91            osg::StateAttribute* attr = stateset->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
92            if (attr)
93            {
94                osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(attr);
95                if (texture2D) apply(dynamic_cast<osg::ImageStream*>(texture2D->getImage()));
96
97                osg::TextureRectangle* textureRec = dynamic_cast<osg::TextureRectangle*>(attr);
98                if (textureRec) apply(dynamic_cast<osg::ImageStream*>(textureRec->getImage()));
99            }
100        }
[9705]101
[2810]102        inline void apply(osg::ImageStream* imagestream)
103        {
[3819]104            if (imagestream)
105            {
[9705]106                _imageStreamList.push_back(imagestream);
[3819]107            }
[2810]108        }
[9705]109
[2810]110        ImageStreamList& _imageStreamList;
[9637]111
112    protected:
[9705]113
[9637]114        FindImageStreamsVisitor& operator = (const FindImageStreamsVisitor&) { return *this; }
115
[2810]116    };
117
118
[6624]119    bool            _trackMouse;
[2810]120    ImageStreamList _imageStreamList;
[9705]121
[2810]122};
123
124
125
126void MovieEventHandler::set(osg::Node* node)
127{
128    _imageStreamList.clear();
129    if (node)
130    {
131        FindImageStreamsVisitor fisv(_imageStreamList);
132        node->accept(fisv);
133    }
134}
135
136
[4956]137bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
[2810]138{
139    switch(ea.getEventType())
140    {
[4956]141        case(osgGA::GUIEventAdapter::MOVE):
142        case(osgGA::GUIEventAdapter::PUSH):
143        case(osgGA::GUIEventAdapter::RELEASE):
144        {
[6624]145            if (_trackMouse)
[4956]146            {
[6624]147                osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
148                osgUtil::LineSegmentIntersector::Intersections intersections;
[8073]149                bool foundIntersection = view==0 ? false :
150                    (nv==0 ? view->computeIntersections(ea.getX(), ea.getY(), intersections) :
151                             view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections));
[9705]152
[8073]153                if (foundIntersection)
[4956]154                {
155
[9705]156                    // use the nearest intersection
[6624]157                    const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin());
158                    osg::Drawable* drawable = intersection.drawable.get();
159                    osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0;
160                    osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
161                    if (vertices)
[4956]162                    {
[6624]163                        // get the vertex indices.
164                        const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList;
165                        const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList;
[4956]166
[6624]167                        if (indices.size()==3 && ratios.size()==3)
[4956]168                        {
[6624]169                            unsigned int i1 = indices[0];
170                            unsigned int i2 = indices[1];
171                            unsigned int i3 = indices[2];
[5951]172
[6624]173                            float r1 = ratios[0];
174                            float r2 = ratios[1];
175                            float r3 = ratios[2];
[5951]176
[6624]177                            osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
178                            osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
179                            if (texcoords_Vec2Array)
180                            {
[9705]181                                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
[6624]182                                osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1];
183                                osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2];
184                                osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3];
185                                osg::Vec2 tc = tc1*r1 + tc2*r2 + tc3*r3;
186
187                                osg::notify(osg::NOTICE)<<"We hit tex coords "<<tc<<std::endl;
188
189                            }
[4956]190                        }
[6624]191                        else
192                        {
193                            osg::notify(osg::NOTICE)<<"Intersection has insufficient indices to work with";
194                        }
195
[4956]196                    }
[5951]197                }
[6624]198                else
199                {
200                    osg::notify(osg::NOTICE)<<"No intersection"<<std::endl;
201                }
[4956]202            }
203            break;
204        }
[2810]205        case(osgGA::GUIEventAdapter::KEYDOWN):
206        {
[7615]207            if (ea.getKey()=='p')
[2810]208            {
209                for(ImageStreamList::iterator itr=_imageStreamList.begin();
210                    itr!=_imageStreamList.end();
211                    ++itr)
212                {
[10799]213                    osg::ImageStream::StreamStatus playToggle = (*itr)->getStatus();
214                    if (playToggle != osg::ImageStream::PLAYING)
[7615]215                    {
[10799]216                        std::cout<< (*itr).get() << " Play"<<std::endl;
[7615]217                        (*itr)->play();
218                    }
219                    else
220                    {
221                        // playing, so pause
[10799]222                        std::cout<< (*itr).get() << " Pause"<<std::endl;
[7615]223                        (*itr)->pause();
224                    }
[2810]225                }
226                return true;
227            }
228            else if (ea.getKey()=='r')
229            {
[4520]230                for(ImageStreamList::iterator itr=_imageStreamList.begin();
231                    itr!=_imageStreamList.end();
232                    ++itr)
233                {
[10799]234                    std::cout<< (*itr).get() << " Restart"<<std::endl;
[4520]235                    (*itr)->rewind();
236                    (*itr)->play();
237                }
[2810]238                return true;
239            }
[7615]240            else if (ea.getKey()=='L')
[2810]241            {
[4520]242                for(ImageStreamList::iterator itr=_imageStreamList.begin();
243                    itr!=_imageStreamList.end();
244                    ++itr)
245                {
246                    if ( (*itr)->getLoopingMode() == osg::ImageStream::LOOPING)
247                    {
[10799]248                        std::cout<< (*itr).get() << " Toggle Looping Off"<<std::endl;
[4520]249                        (*itr)->setLoopingMode( osg::ImageStream::NO_LOOPING );
250                    }
251                    else
252                    {
[10799]253                        std::cout<< (*itr).get() << " Toggle Looping On"<<std::endl;
[4520]254                        (*itr)->setLoopingMode( osg::ImageStream::LOOPING );
255                    }
256                }
[2810]257                return true;
258            }
[10799]259            else if (ea.getKey()=='+')
260            {
261                for(ImageStreamList::iterator itr=_imageStreamList.begin();
262                    itr!=_imageStreamList.end();
263                    ++itr)
264                {
265                    double tm = (*itr)->getTimeMultiplier();
266                    tm += 0.1;
267                    (*itr)->setTimeMultiplier(tm);
268                    std::cout << (*itr).get() << " Increase speed rate "<< (*itr)->getTimeMultiplier() << std::endl;
269                }
270                return true;
271            }
272            else if (ea.getKey()=='-')
273            {
274                for(ImageStreamList::iterator itr=_imageStreamList.begin();
275                    itr!=_imageStreamList.end();
276                    ++itr)
277                {
278                    double tm = (*itr)->getTimeMultiplier();
279                    tm -= 0.1;
280                    (*itr)->setTimeMultiplier(tm);
281                    std::cout << (*itr).get() << " Decrease speed rate "<< (*itr)->getTimeMultiplier() << std::endl;
282                }
283                return true;
284            }
285            else if (ea.getKey()=='o')
286            {
287                for(ImageStreamList::iterator itr=_imageStreamList.begin();
288                    itr!=_imageStreamList.end();
289                    ++itr)
290                {
291                    std::cout<< (*itr).get() << " Frame rate  "<< (*itr)->getFrameRate() <<std::endl;
292                }
293                return true;
294            }
[2810]295            return false;
296        }
297
298        default:
299            return false;
300    }
[4956]301    return false;
[2810]302}
303
304void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
305{
[7615]306    usage.addKeyboardMouseBinding("p","Play/Pause movie");
[4520]307    usage.addKeyboardMouseBinding("r","Restart movie");
[2810]308    usage.addKeyboardMouseBinding("l","Toggle looping of movie");
[10799]309    usage.addKeyboardMouseBinding("+","Increase speed of movie");
310    usage.addKeyboardMouseBinding("-","Decrease speed of movie");
311    usage.addKeyboardMouseBinding("o","Display frame rate of movie");
[2810]312}
313
314
[7479]315osg::Geometry* myCreateTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image, bool useTextureRectangle, bool xyPlane, bool option_flip)
[2693]316{
[6947]317    bool flip = image->getOrigin()==osg::Image::TOP_LEFT;
[7479]318    if (option_flip) flip = !flip;
[9705]319
[2809]320    if (useTextureRectangle)
321    {
[4746]322        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
[2809]323                                           osg::Vec3(width,0.0f,0.0f),
[7477]324                                           xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height),
[6947]325                                           0.0f, flip ? image->t() : 0.0, image->s(), flip ? 0.0 : image->t());
[4321]326
[6941]327        osg::TextureRectangle* texture = new osg::TextureRectangle(image);
328        texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
329        texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
[9705]330
331
[2809]332        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
[6941]333                                                                        texture,
334                                                                        osg::StateAttribute::ON);
[9705]335
[2809]336        return pictureQuad;
[2693]337    }
[2809]338    else
339    {
[4746]340        osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(pos,
[2809]341                                           osg::Vec3(width,0.0f,0.0f),
[7477]342                                           xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height),
[6947]343                                           0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f);
[9705]344
[4321]345        osg::Texture2D* texture = new osg::Texture2D(image);
[8857]346        texture->setResizeNonPowerOfTwoHint(false);
[6941]347        texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
348        texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
349        texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
[9705]350
351
[2809]352        pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
[4321]353                    texture,
[2809]354                    osg::StateAttribute::ON);
[2693]355
[2809]356        return pictureQuad;
357    }
[2693]358}
359
[9849]360#if USE_SDL
361
362class SDLAudioSink : public osg::AudioSink
[9847]363{
364    public:
[10188]365
[9849]366        SDLAudioSink(osg::AudioStream* audioStream):
[9847]367            _playing(false),
368            _audioStream(audioStream) {}
[9849]369
[10188]370        ~SDLAudioSink();
[9849]371
[10188]372        virtual void startPlaying();
[9847]373        virtual bool playing() const { return _playing; }
374
[9849]375
[9847]376        bool                                _playing;
377        osg::observer_ptr<osg::AudioStream> _audioStream;
378};
379
[9849]380#endif
381
[2693]382int main(int argc, char** argv)
383{
384    // use an ArgumentParser object to manage the program arguments.
385    osg::ArgumentParser arguments(&argc,argv);
[9705]386
[2693]387    // set up the usage document, in case we need to print out how to use this program.
388    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
[4780]389    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" example demonstrates the use of ImageStream for rendering movies as textures.");
[2693]390    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
391    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
[5927]392    arguments.getApplicationUsage()->addCommandLineOption("--texture2D","Use Texture2D rather than TextureRectangle.");
393    arguments.getApplicationUsage()->addCommandLineOption("--shader","Use shaders to post process the video.");
[7480]394    arguments.getApplicationUsage()->addCommandLineOption("--interactive","Use camera manipulator to allow movement around movie.");
395    arguments.getApplicationUsage()->addCommandLineOption("--flip","Flip the movie so top becomes bottom.");
[9705]396#if defined(WIN32) || defined(__APPLE__)
[7594]397    arguments.getApplicationUsage()->addCommandLineOption("--devices","Print the Video input capability via QuickTime and exit.");
[9705]398#endif
399
[4321]400    bool useTextureRectangle = true;
401    bool useShader = false;
[2693]402
403    // construct the viewer.
[7475]404    osgViewer::Viewer viewer(arguments);
[9705]405
[6625]406    if (arguments.argc()<=1)
407    {
408        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
409        return 1;
410    }
411
[9705]412#if defined(WIN32) || defined(__APPLE__)
[7594]413    // if user requests devices video capability.
414    if (arguments.read("-devices") || arguments.read("--devices"))
415    {
416        // Force load QuickTime plugin, probe video capability, exit
417        osgDB::readImageFile("devices.live");
418        return 1;
419    }
[9705]420#endif
[7594]421
[4321]422    while (arguments.read("--texture2D")) useTextureRectangle=false;
423    while (arguments.read("--shader")) useShader=true;
[2693]424
[8073]425    bool mouseTracking = false;
[9705]426    while (arguments.read("--mouse")) mouseTracking=true;
[8073]427
428
[2693]429    // if user request help write it out to cout.
430    if (arguments.read("-h") || arguments.read("--help"))
431    {
432        arguments.getApplicationUsage()->write(std::cout);
433        return 1;
434    }
435
[7477]436    bool fullscreen = !arguments.read("--interactive");
[7479]437    bool flip = arguments.read("--flip");
[4321]438
[7477]439    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
[4322]440
[7477]441    osg::StateSet* stateset = geode->getOrCreateStateSet();
442    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
[4322]443
[7477]444    if (useShader)
445    {
446        //useTextureRectangle = false;
[4321]447
[7477]448        static const char *shaderSourceTextureRec = {
449            "uniform vec4 cutoff_color;\n"
450            "uniform samplerRect movie_texture;\n"
451            "void main(void)\n"
452            "{\n"
[8857]453            "    vec4 texture_color = textureRect(movie_texture, gl_TexCoord[0].st); \n"
[7477]454            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
455            "    gl_FragColor = texture_color;\n"
456            "}\n"
457        };
[4321]458
[7477]459        static const char *shaderSourceTexture2D = {
460            "uniform vec4 cutoff_color;\n"
461            "uniform sampler2D movie_texture;\n"
462            "void main(void)\n"
463            "{\n"
[8857]464            "    vec4 texture_color = texture2D(movie_texture, gl_TexCoord[0].st); \n"
[7477]465            "    if (all(lessThanEqual(texture_color,cutoff_color))) discard; \n"
466            "    gl_FragColor = texture_color;\n"
467            "}\n"
468        };
[4321]469
[7477]470        osg::Program* program = new osg::Program;
[4321]471
[7477]472        program->addShader(new osg::Shader(osg::Shader::FRAGMENT,
473                                           useTextureRectangle ? shaderSourceTextureRec : shaderSourceTexture2D));
[4321]474
[7477]475        stateset->addUniform(new osg::Uniform("cutoff_color",osg::Vec4(0.1f,0.1f,0.1f,1.0f)));
476        stateset->addUniform(new osg::Uniform("movie_texture",0));
[6625]477
[7477]478        stateset->setAttribute(program);
[6625]479
[7477]480    }
[6625]481
[7477]482    osg::Vec3 pos(0.0f,0.0f,0.0f);
483    osg::Vec3 topleft = pos;
484    osg::Vec3 bottomright = pos;
[9705]485
[7477]486    bool xyPlane = fullscreen;
[9847]487   
[9849]488    bool useAudioSink = false;
489    while(arguments.read("--audio")) { useAudioSink = true; }
[9914]490   
[9928]491#if USE_SDL
[9914]492    unsigned int numAudioStreamsEnabled = 0;
[9928]493#endif
[9705]494
[7477]495    for(int i=1;i<arguments.argc();++i)
496    {
497        if (arguments.isString(i))
[2809]498        {
[7477]499            osg::Image* image = osgDB::readImageFile(arguments[i]);
500            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
[9847]501            if (imagestream)
502            {
503                osg::ImageStream::AudioStreams& audioStreams = imagestream->getAudioStreams();
[9849]504                if (useAudioSink && !audioStreams.empty())
[9847]505                {
506                    osg::AudioStream* audioStream = audioStreams[0].get();
507                    osg::notify(osg::NOTICE)<<"AudioStream read ["<<audioStream->getName()<<"]"<<std::endl;
[9849]508#if USE_SDL
[9914]509                    if (numAudioStreamsEnabled==0)
510                    {
511                        audioStream->setAudioSink(new SDLAudioSink(audioStream));
512                       
513                        ++numAudioStreamsEnabled;
514                    }
[9849]515#endif
[9847]516                }
[7477]517
[9847]518
519                imagestream->play();
520            }
521
[7477]522            if (image)
[4082]523            {
[9911]524                osg::notify(osg::NOTICE)<<"image->s()"<<image->s()<<" image-t()="<<image->t()<<" aspectRatio="<<image->getPixelAspectRatio()<<std::endl;
[9705]525
[9913]526                float width = image->s() * image->getPixelAspectRatio();
527                float height = image->t();
[9705]528
[9911]529                osg::ref_ptr<osg::Drawable> drawable = myCreateTexturedQuadGeometry(pos, width, height,image, useTextureRectangle, xyPlane, flip);
530               
531                if (image->isImageTranslucent())
532                {
533                    osg::notify(osg::NOTICE)<<"Transparent movie, enabling blending."<<std::endl;
[6624]534
[9911]535                    drawable->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
536                    drawable->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
537                }
538
539                geode->addDrawable(drawable.get());
540
541                bottomright = pos + osg::Vec3(width,height,0.0f);
542
543                if (xyPlane) pos.y() += height*1.05f;
544                else pos.z() += height*1.05f;
[4082]545            }
[7477]546            else
547            {
548                std::cout<<"Unable to read file "<<arguments[i]<<std::endl;
[9705]549            }
[2809]550        }
551    }
[9705]552
[7477]553    // set the scene to render
554    viewer.setSceneData(geode.get());
[2809]555
[7477]556    if (viewer.getSceneData()==0)
557    {
558        arguments.getApplicationUsage()->write(std::cout);
559        return 1;
560    }
561
[2810]562    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
[4956]563    MovieEventHandler* meh = new MovieEventHandler();
[8073]564    meh->setMouseTracking( mouseTracking );
[7615]565    meh->set( viewer.getSceneData() );
566    viewer.addEventHandler( meh );
[2809]567
[7615]568    viewer.addEventHandler( new osgViewer::StatsHandler );
569    viewer.addEventHandler( new osgGA::StateSetManipulator( viewer.getCamera()->getOrCreateStateSet() ) );
570    viewer.addEventHandler( new osgViewer::WindowSizeHandler );
571
572    // add the record camera path handler
573    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
574
[7648]575    // report any errors if they have occurred when parsing the program arguments.
[2693]576    if (arguments.errors())
577    {
578        arguments.writeErrorMessages(std::cout);
579        return 1;
580    }
581
[7477]582    if (fullscreen)
583    {
584        viewer.realize();
[9911]585       
586        viewer.getCamera()->setClearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
[6624]587
[9911]588        float screenAspectRatio = 1280.0f/1024.0f;
589
590        osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
591        if (wsi)
592        {
593            unsigned int width, height;
594            wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);
595           
596            screenAspectRatio = float(width) / float(height);
597        }
598       
599        float modelAspectRatio = (bottomright.x()-topleft.x())/(bottomright.y()-topleft.y());
600       
[7477]601        viewer.getCamera()->setViewMatrix(osg::Matrix::identity());
[9911]602
603
604        osg::Vec3 center = (bottomright + topleft)*0.5f;
605        osg::Vec3 dx(bottomright.x()-center.x(), 0.0f, 0.0f);
606        osg::Vec3 dy(0.0f, topleft.y()-center.y(), 0.0f);
607
608        float ratio = modelAspectRatio/screenAspectRatio;
609
610        if (ratio>1.0f)
611        {
612            // use model width as the control on model size.
613            bottomright = center + dx - dy * ratio;
614            topleft = center - dx + dy * ratio;
615        }
616        else
617        {
618            // use model height as the control on model size.
619            bottomright = center + dx / ratio - dy;
620            topleft = center - dx / ratio + dy;
621        }
622
[7477]623        viewer.getCamera()->setProjectionMatrixAsOrtho2D(topleft.x(),bottomright.x(),topleft.y(),bottomright.y());
[2693]624
[7477]625        while(!viewer.done())
626        {
627            viewer.frame();
628        }
629        return 0;
630    }
631    else
632    {
633        // create the windows and run the threads.
634        return viewer.run();
635    }
[2693]636}
[9705]637
[10188]638#if USE_SDL
639
640#include "SDL.h"
641
[10193]642static void soundReadCallback(void * user_data, uint8_t * data, int datalen)
643{
644    SDLAudioSink * sink = reinterpret_cast<SDLAudioSink*>(user_data);
645    osg::ref_ptr<osg::AudioStream> as = sink->_audioStream.get();
646    if (as.valid())
647    {
648        as->consumeAudioBuffer(data, datalen);
649    }
650}
651
[10188]652SDLAudioSink::~SDLAudioSink()
653{
654    if (_playing)
655    {
656
657        SDL_PauseAudio(1);
658        SDL_CloseAudio();
659
660        osg::notify(osg::NOTICE)<<"~SDLAudioSink() destructor, but still playing"<<std::endl;
661    }
662}
663
664void SDLAudioSink::startPlaying()
665{
666    _playing = true;
667    osg::notify(osg::NOTICE)<<"SDLAudioSink()::startPlaying()"<<std::endl;
668
669    osg::notify(osg::NOTICE)<<"  audioFrequency()="<<_audioStream->audioFrequency()<<std::endl;
670    osg::notify(osg::NOTICE)<<"  audioNbChannels()="<<_audioStream->audioNbChannels()<<std::endl;
671    osg::notify(osg::NOTICE)<<"  audioSampleFormat()="<<_audioStream->audioSampleFormat()<<std::endl;
672
673    SDL_AudioSpec specs = { 0 };
674    SDL_AudioSpec wanted_specs = { 0 };
675
676    wanted_specs.freq = _audioStream->audioFrequency();
677    wanted_specs.format = AUDIO_S16SYS;
678    wanted_specs.channels = _audioStream->audioNbChannels();
679    wanted_specs.silence = 0;
680    wanted_specs.samples = 1024;
681    wanted_specs.callback = soundReadCallback;
682    wanted_specs.userdata = this;
683
684    if (SDL_OpenAudio(&wanted_specs, &specs) < 0)
685        throw "SDL_OpenAudio() failed (" + std::string(SDL_GetError()) + ")";
686
687    SDL_PauseAudio(0);
688
689}
690
691
692#endif
Note: See TracBrowser for help on using the browser.