root/OpenSceneGraph/trunk/examples/osgphotoalbum/osgphotoalbum.cpp @ 2539

Revision 2539, 26.5 kB (checked in by robert, 11 years ago)

Added gemetry of photo album and page turning animation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgProducer/Viewer>
15#include <osgDB/ReadFile>
16#include <osgDB/WriteFile>
17#include <osgDB/ImageOptions>
18
19#include <osgUtil/Optimizer>
20
21#include <osg/Geode>
22#include <osg/Notify>
23#include <osg/MatrixTransform>
24#include <osg/Switch>
25#include <osg/TexMat>
26#include <osg/Texture2D>
27#include <osg/PolygonOffset>
28
29#include <osgText/Text>
30
31#include <sstream>
32
33class ImageReaderWriter : public osgDB::ReaderWriter
34{
35    public:
36        virtual const char* className() { return "Image Reader"; }
37       
38       
39        struct DataReference
40        {
41            DataReference():
42                _fileName(),
43                _resolutionX(256),
44                _resolutionY(256),
45                _center(0.625f,0.0f,0.0f),
46                _maximumWidth(1.25f,0.0f,0.0f),
47                _maximumHeight(0.0f,0.0f,1.0f),
48                _numPointsAcross(10),
49                _numPointsUp(10) {}
50
51            DataReference(const std::string& fileName, unsigned int res, float width, float height):
52                _fileName(fileName),
53                _resolutionX(res),
54                _resolutionY(res),
55                _center(width*0.5f,0.0f,height*0.5f),
56                _maximumWidth(width,0.0f,0.0f),
57                _maximumHeight(0.0f,0.0f,height),
58                _numPointsAcross(10),
59                _numPointsUp(10) {}
60       
61            DataReference(const DataReference& rhs):
62                _fileName(rhs._fileName),
63                _resolutionX(rhs._resolutionX),
64                _resolutionY(rhs._resolutionY),
65                _center(rhs._center),
66                _maximumWidth(rhs._maximumWidth),
67                _maximumHeight(rhs._maximumHeight),
68                _numPointsAcross(rhs._numPointsAcross),
69                _numPointsUp(rhs._numPointsUp) {}
70
71            std::string     _fileName;
72            unsigned int    _resolutionX;
73            unsigned int    _resolutionY;
74            osg::Vec3       _center;
75            osg::Vec3       _maximumWidth;
76            osg::Vec3       _maximumHeight;
77            unsigned int    _numPointsAcross;
78            unsigned int    _numPointsUp;
79        };
80       
81        typedef std::map<std::string,DataReference> DataReferenceMap;
82        DataReferenceMap _dataReferences;
83       
84        std::string insertReference(const std::string& fileName, unsigned int res, float width, float height)
85        {
86            std::stringstream ostr;
87            ostr<<"res_"<<res<<"_"<<fileName;
88
89            std::string myReference = ostr.str();
90            _dataReferences[myReference] = DataReference(fileName,res,width,height);
91            return myReference;
92        }
93       
94       
95
96        virtual ReadResult readNode(const std::string& fileName, const Options* opt)
97        {
98            std::cout<<"Trying to read paged image "<<fileName<<std::endl;
99           
100            DataReferenceMap::iterator itr = _dataReferences.find(fileName);
101            if (itr==_dataReferences.end()) return ReaderWriter::ReadResult::FILE_NOT_HANDLED;
102
103            DataReference& dr = itr->second;
104           
105            // record previous options.
106            osg::ref_ptr<osgDB::ReaderWriter::Options> previousOptions = osgDB::Registry::instance()->getOptions();
107
108            osg::ref_ptr<osgDB::ImageOptions> options = new osgDB::ImageOptions;
109            options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW;
110            options->_destinationPixelWindow.set(0,0,dr._resolutionX,dr._resolutionY);
111
112            osgDB::Registry::instance()->setOptions(options.get());
113           
114            osg::Image* image = osgDB::readImageFile(dr._fileName);
115           
116            // restore previous options.
117            osgDB::Registry::instance()->setOptions(previousOptions.get());
118
119            if (image)
120            {
121           
122                float s = options.valid()?options->_sourcePixelWindow.windowWidth:1.0f;
123                float t = options.valid()?options->_sourcePixelWindow.windowHeight:1.0f;
124           
125                float photoWidth = 0.0f;
126                float photoHeight = 0.0f;
127                float maxWidth = dr._maximumWidth.length();
128                float maxHeight = dr._maximumHeight.length();
129               
130               
131                if ((s/t)>(maxWidth/maxHeight))
132                {
133                    // photo wider than tall relative to the required pictures size.
134                    // so need to clamp the width to the maximum width and then
135                    // set the height to keep the original photo aspect ratio.
136                   
137                    photoWidth = maxWidth;
138                    photoHeight = photoWidth*(t/s);
139                }
140                else
141                {
142                    // photo tall than wide relative to the required pictures size.
143                    // so need to clamp the height to the maximum height and then
144                    // set the width to keep the original photo aspect ratio.
145                   
146                    photoHeight = maxHeight;
147                    photoWidth = photoHeight*(s/t);
148                }
149               
150                osg::Vec3 halfWidthVector(dr._maximumWidth*(photoWidth*0.5f/maxWidth));
151                osg::Vec3 halfHeightVector(dr._maximumHeight*(photoHeight*0.5f/maxHeight));
152
153
154                // set up the texture.
155                osg::Texture2D* texture = new osg::Texture2D;
156                texture->setImage(image);
157                texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
158                texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
159
160                // set up the drawstate.
161                osg::StateSet* dstate = new osg::StateSet;
162                dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
163                dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
164
165                // set up the geoset.
166                osg::Geometry* geom = new osg::Geometry;
167                geom->setStateSet(dstate);
168
169                osg::Vec3Array* coords = new osg::Vec3Array(4);
170                (*coords)[0] = dr._center - halfWidthVector + halfHeightVector;
171                (*coords)[1] = dr._center - halfWidthVector - halfHeightVector;
172                (*coords)[2] = dr._center + halfWidthVector - halfHeightVector;
173                (*coords)[3] = dr._center + halfWidthVector + halfHeightVector;
174                geom->setVertexArray(coords);
175
176                osg::Vec2Array* tcoords = new osg::Vec2Array(4);
177                (*tcoords)[0].set(0.0f,1.0f);
178                (*tcoords)[1].set(0.0f,0.0f);
179                (*tcoords)[2].set(1.0f,0.0f);
180                (*tcoords)[3].set(1.0f,1.0f);
181                geom->setTexCoordArray(0,tcoords);
182
183                osg::Vec4Array* colours = new osg::Vec4Array(1);
184                (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
185                geom->setColorArray(colours);
186                geom->setColorBinding(osg::Geometry::BIND_OVERALL);
187
188                geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
189
190                // set up the geode.
191                osg::Geode* geode = new osg::Geode;
192                geode->addDrawable(geom);
193               
194                return geode;
195           
196            }
197            else
198            {
199                return ReaderWriter::ReadResult::FILE_NOT_HANDLED;
200            }
201           
202                       
203        }
204
205};
206
207
208// now register with Registry to instantiate the above
209// reader/writer.
210osgDB::RegisterReaderWriterProxy<ImageReaderWriter> g_ImageReaderWriter;
211
212class Album;
213
214class Page : public osg::Transform
215{
216public:
217
218
219    static Page* createPage(Album* album, unsigned int pageNo, const std::string& filename, float width, float height)
220    {
221        osg::ref_ptr<Page> page = new Page(album, pageNo, filename, width, height);
222        if (page.valid()) return page.release();
223        else return 0;
224    }
225   
226    virtual void traverse(osg::NodeVisitor& nv);
227
228    void setRotation(float angle)
229    {
230        _rotation = angle;
231        _targetRotation = angle;
232        dirtyBound();
233    }
234
235    float getRotation() const { return _rotation; }
236
237    void rotateTo(float angle, float timeToRotateBy)
238    {
239        _targetRotation = angle;
240        _targetTime = timeToRotateBy;
241    }
242   
243    bool rotating() const { return _targetRotation!=_rotation; }
244
245    void setPageVisible(bool visible) { _switch->setSingleChildOn(visible?1:0); }
246
247    osg::Switch* getSwitch() { return _switch.get(); }
248    const osg::Switch* getSwitch() const { return _switch.get(); }
249
250public:
251
252    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const 
253    {
254        if (_referenceFrame==RELATIVE_TO_PARENTS)
255        {
256            matrix.preMult(getMatrix());
257        }
258        else // absolute
259        {
260            matrix = getMatrix();
261        }
262        return true;
263    }
264
265    /** Get the transformation matrix which moves from world coords to local coords.*/
266    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
267    {
268        const osg::Matrix& inverse = getInverseMatrix();
269
270        if (_referenceFrame==RELATIVE_TO_PARENTS)
271        {
272            matrix.postMult(inverse);
273        }
274        else // absolute
275        {
276            matrix = inverse;
277        }
278        return true;
279    }
280
281    osg::Matrix getMatrix() const { return _pageOffset*osg::Matrix::rotate(-_rotation,0.0f,0.0f,1.0f); }
282    osg::Matrix getInverseMatrix() const { return osg::Matrix::inverse(getMatrix()); }
283
284protected:
285   
286    Page(Album* album, unsigned int pageNo, const std::string& filename, float width, float height);
287
288    float       _rotation;
289    osg::Matrix _pageOffset;
290
291    float       _targetRotation;
292    float       _targetTime;
293    float       _lastTimeTraverse;
294
295    osg::ref_ptr<osg::Switch>     _switch;
296
297};
298
299
300class Album : public osg::Referenced
301{
302public:
303
304    Album(osg::ArgumentParser& ap, float width, float height);
305
306    osg::Group* getScene() { return _group.get(); }
307   
308    const osg::Group* getScene() const { return _group.get(); }
309
310    osg::Matrix getPageOffset(unsigned int pageNo) const;
311   
312    bool nextPage(float timeToRotateBy) { return gotoPage(_currentPageNo+1,timeToRotateBy); }
313
314    bool previousPage(float timeToRotateBy) { return _currentPageNo>=1?gotoPage(_currentPageNo-1,timeToRotateBy):false; }
315   
316    bool gotoPage(unsigned int pageNo, float timeToRotateBy);
317   
318    osg::StateSet* getBackgroundStateSet() { return _backgroundStateSet.get(); }
319   
320    void setVisibility();
321
322protected:
323
324    typedef std::vector< osg::ref_ptr<Page> > PageList;
325
326    osg::ref_ptr<osg::Group>    _group;
327    PageList                    _pages;
328   
329    osg::ref_ptr<osg::StateSet> _backgroundStateSet;
330   
331    unsigned int                _currentPageNo;
332    float                       _radiusOfRings;
333    float                       _startAngleOfPages;
334    float                       _deltaAngleBetweenPages;   
335
336};
337
338
339////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
340
341
342Page::Page(Album* album, unsigned int pageNo, const std::string& filename, float width, float height)
343{
344    // set up transform parts.
345    _rotation = 0;
346    _targetRotation = 0;
347    _targetTime = 0;
348    _lastTimeTraverse = 0;
349   
350    _pageOffset = album->getPageOffset(pageNo);
351   
352    setNumChildrenRequiringUpdateTraversal(1);
353   
354   
355    // set up subgraph
356    osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal");
357    if (!readerWriter)
358    {
359        std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"<<std::endl;
360    }
361
362    _switch = new osg::Switch;
363
364    ImageReaderWriter* rw = g_ImageReaderWriter.get();
365
366   
367    // set up non visible page.
368    osg::Group* non_visible_page = new osg::Group;
369    _switch->addChild(non_visible_page);
370    {
371        // just an empty group for the time being... will need to create geometry soon.
372        osg::Geometry* geom = new osg::Geometry;
373        geom->setStateSet(album->getBackgroundStateSet());
374
375        osg::Vec3Array* coords = new osg::Vec3Array(4);
376        (*coords)[0].set(0.0f,0.0,height);
377        (*coords)[1].set(0.0f,0.0,0);
378        (*coords)[2].set(width,0.0,0);
379        (*coords)[3].set(width,0.0,height);
380        geom->setVertexArray(coords);
381
382        osg::Vec3Array* normals = new osg::Vec3Array(1);
383        (*normals)[0].set(0.0f,-1.0f,0.0f);
384        geom->setNormalArray(normals);
385        geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
386
387        osg::Vec2Array* tcoords = new osg::Vec2Array(4);
388        (*tcoords)[0].set(0.0f,1.0f);
389        (*tcoords)[1].set(0.0f,0.0f);
390        (*tcoords)[2].set(1.0f,0.0f);
391        (*tcoords)[3].set(1.0f,1.0f);
392        geom->setTexCoordArray(0,tcoords);
393
394        osg::Vec4Array* colours = new osg::Vec4Array(1);
395        (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
396        geom->setColorArray(colours);
397        geom->setColorBinding(osg::Geometry::BIND_OVERALL);
398
399        geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,4));
400
401        // set up the geode.
402        osg::Geode* geode = new osg::Geode;
403        geode->addDrawable(geom);
404       
405   
406        non_visible_page->addChild(geode);
407    }
408
409
410    // set up visible page.
411    osg::Group* visible_page = new osg::Group;
412    _switch->addChild(visible_page);
413
414    {
415
416       
417        osg::Geometry* geom = new osg::Geometry;
418        geom->setStateSet(album->getBackgroundStateSet());
419
420        osg::Vec3Array* coords = new osg::Vec3Array(4);
421        (*coords)[0].set(0.0f,0.0,height);
422        (*coords)[1].set(0.0f,0.0,0);
423        (*coords)[2].set(width,0.0,0);
424        (*coords)[3].set(width,0.0,height);
425        geom->setVertexArray(coords);
426
427        osg::Vec3Array* normals = new osg::Vec3Array(1);
428        (*normals)[0].set(0.0f,-1.0f,0.0f);
429        geom->setNormalArray(normals);
430        geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
431
432        osg::Vec2Array* tcoords = new osg::Vec2Array(4);
433        (*tcoords)[0].set(0.0f,1.0f);
434        (*tcoords)[1].set(0.0f,0.0f);
435        (*tcoords)[2].set(1.0f,0.0f);
436        (*tcoords)[3].set(1.0f,1.0f);
437        geom->setTexCoordArray(0,tcoords);
438
439        osg::Vec4Array* colours = new osg::Vec4Array(1);
440        (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
441        geom->setColorArray(colours);
442        geom->setColorBinding(osg::Geometry::BIND_OVERALL);
443
444        geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
445
446        // set up the geode.
447        osg::Geode* geode = new osg::Geode;
448        geode->addDrawable(geom);
449       
450   
451        visible_page->addChild(geode);
452    }
453
454    {
455        float cut_off_distance = 8.0f;
456        float max_visible_distance = 300.0f;
457       
458        osg::Vec3 center(width*0.5f,0.0f,height*0.5f);
459
460        osgText::Text* text = new osgText::Text;
461        text->setFont("fonts/arial.ttf");
462        text->setPosition(center);
463        text->setCharacterSize(height/20.0f);
464        text->setAlignment(osgText::Text::CENTER_CENTER);
465        text->setAxisAlignment(osgText::Text::XZ_PLANE);
466        text->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
467        text->setText(std::string("Loading ")+filename);
468
469        osg::Geode* geode = new osg::Geode;
470        geode->addDrawable(text);
471       
472        osg::PagedLOD* pagedlod = new osg::PagedLOD;
473        pagedlod->setCenter(center);
474        pagedlod->setRadius(1.6f);
475        pagedlod->setNumChildrenThatCannotBeExpired(2);
476       
477        pagedlod->setRange(0,max_visible_distance,1e7);
478        pagedlod->addChild(geode);
479       
480        pagedlod->setRange(1,cut_off_distance,max_visible_distance);
481        pagedlod->setFileName(1,rw->insertReference(filename,256,width,height));
482
483        pagedlod->setRange(2,0.0f,cut_off_distance);
484        pagedlod->setFileName(2,rw->insertReference(filename,1024,width,height));
485
486        visible_page->addChild(pagedlod);
487    }
488   
489    addChild(_switch.get());
490}
491
492void Page::traverse(osg::NodeVisitor& nv)
493{
494    // if app traversal update the frame count.
495    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
496    {
497        const osg::FrameStamp* framestamp = nv.getFrameStamp();
498        if (framestamp)
499        {
500            double t = framestamp->getReferenceTime();
501           
502            if (_rotation!=_targetRotation)
503            {
504                if (t>=_targetTime) _rotation = _targetRotation;
505                else _rotation += (_targetRotation-_rotation)*(t-_lastTimeTraverse)/(_targetTime-_lastTimeTraverse);
506               
507                dirtyBound();
508            }
509           
510            _lastTimeTraverse = t;
511
512        }
513    }
514    Transform::traverse(nv);
515}
516
517
518////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
519
520Album::Album(osg::ArgumentParser& arguments, float width, float height)
521{
522
523
524    typedef std::vector<std::string> FileList;
525    FileList fileList;
526
527    for(int pos=1;pos<arguments.argc();++pos)
528    {
529        if (arguments.isString(pos)) fileList.push_back(arguments[pos]);
530    }
531   
532    _radiusOfRings = 0.02;
533    _startAngleOfPages = 0.0f;
534    _deltaAngleBetweenPages = osg::PI/(float)fileList.size();
535   
536    _group = new osg::Group;
537   
538    _backgroundStateSet = new osg::StateSet;
539    _backgroundStateSet->setAttributeAndModes(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);
540   
541    // load the images.
542    unsigned int i;
543    for(i=0;i<fileList.size();++i)
544    {
545        Page* page = Page::createPage(this,_pages.size(),fileList[i], width, height);
546        if (page)
547        {
548            _pages.push_back(page);
549            _group->addChild(page);
550        }
551    }
552   
553    setVisibility();
554
555}
556
557osg::Matrix Album::getPageOffset(unsigned int pageNo) const
558{
559    float angleForPage = _startAngleOfPages+_deltaAngleBetweenPages*(float)pageNo;
560    osg::Vec3 delta(_radiusOfRings*sinf(angleForPage),-_radiusOfRings*cosf(angleForPage),0.0f);
561    return osg::Matrix::translate(delta);
562}
563
564bool Album::gotoPage(unsigned int pageNo, float timeToRotateBy)
565{
566    if (pageNo>=_pages.size()) return false;
567
568    if (pageNo>_currentPageNo)
569    {
570        for(unsigned int i=_currentPageNo;i<pageNo;++i)
571        {
572            _pages[i]->rotateTo(osg::PI,timeToRotateBy);
573        }
574        _pages[pageNo]->setPageVisible(true);
575        _currentPageNo = pageNo;
576       
577        return true;
578    }
579    else if (pageNo<_currentPageNo)
580    {
581        for(unsigned int i=pageNo;i<_currentPageNo;++i)
582        {
583            _pages[i]->rotateTo(0,timeToRotateBy);
584        }
585        _pages[pageNo]->setPageVisible(true);
586        _currentPageNo = pageNo;
587       
588        return true;
589    }
590   
591    return false;
592}
593
594void Album::setVisibility()
595{
596    for(unsigned int i=0;i<_pages.size();++i)
597    {
598        _pages[i]->setPageVisible(_pages[i]->rotating());
599    }
600   
601    //_pages[0]->setPageVisible(true);
602    //if (_currentPageNo>=1) _pages[_currentPageNo-1]->setPageVisible(true);
603    _pages[_currentPageNo]->setPageVisible(true);
604    //if (_currentPageNo<_pages.size()-1) _pages[_currentPageNo+1]->setPageVisible(true);
605    //_pages[_pages.size()-1]->setPageVisible(true);
606}
607
608
609////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
610
611
612class SlideEventHandler : public osgGA::GUIEventHandler
613{
614public:
615
616    SlideEventHandler();
617   
618    META_Object(osgStereImageApp,SlideEventHandler);
619
620    void set(Album* album, float timePerSlide, bool autoSteppingActive);
621
622    virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }
623
624    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
625   
626    virtual void getUsage(osg::ApplicationUsage& usage) const;
627
628protected:
629
630    ~SlideEventHandler() {}
631    SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {}
632
633    osg::ref_ptr<Album>         _album;
634    bool                        _firstTraversal;
635    double                      _previousTime;
636    double                      _timePerSlide;
637    bool                        _autoSteppingActive;
638};
639
640SlideEventHandler::SlideEventHandler():
641    _album(0),
642    _firstTraversal(true),
643    _previousTime(-1.0f),
644    _timePerSlide(5.0),
645    _autoSteppingActive(false)
646{
647}
648
649void SlideEventHandler::set(Album* album, float timePerSlide, bool autoSteppingActive)
650{
651    _album = album;
652
653    _timePerSlide = timePerSlide;
654    _autoSteppingActive = autoSteppingActive;   
655   
656}
657
658bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
659{
660    switch(ea.getEventType())
661    {
662        case(osgGA::GUIEventAdapter::KEYDOWN):
663        {
664            if (ea.getKey()=='a')
665            {
666                _autoSteppingActive = !_autoSteppingActive;
667                _previousTime = ea.time();
668                return true;
669            }
670            else if (ea.getKey()=='n')
671            {
672                _album->nextPage(ea.time()+1.0f);
673                return true;
674            }
675            else if (ea.getKey()=='p')
676            {
677                _album->previousPage(ea.time()+1.0f);
678                return true;
679            }
680            return false;
681        }
682        case(osgGA::GUIEventAdapter::FRAME):
683        {
684            if (_autoSteppingActive)
685            {
686                if (_firstTraversal)
687                {
688                    _firstTraversal = false;
689                    _previousTime = ea.time();
690                }
691                else if (ea.time()-_previousTime>_timePerSlide)
692                {
693                    _previousTime = ea.time();
694
695                    _album->nextPage(ea.time()+1.0f);
696                }
697            }
698           
699            _album->setVisibility();
700
701        }
702
703        default:
704            return false;
705    }
706}
707
708void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const
709{
710    usage.addKeyboardMouseBinding("Space","Reset the image position to center");
711    usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image");
712    usage.addKeyboardMouseBinding("n","Advance to next image");
713    usage.addKeyboardMouseBinding("p","Move to previous image");
714}
715
716int main( int argc, char **argv )
717{
718
719    // use an ArgumentParser object to manage the program arguments.
720    osg::ArgumentParser arguments(&argc,argv);
721   
722    // set up the usage document, in case we need to print out how to use this program.
723    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
724    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file [image_file]");
725    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in sceonds between the display of successive image pairs when in auto advance mode.");
726    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
727    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
728   
729
730    // construct the viewer.
731    osgProducer::Viewer viewer(arguments);
732
733    // set up the value with sensible default event handlers.
734    //viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE);
735    viewer.setUpViewer();
736
737    // register the handler to add keyboard and mosue handling.
738    SlideEventHandler* seh = new SlideEventHandler();
739    viewer.getEventHandlerList().push_front(seh);
740
741
742    // get details on keyboard and mouse bindings used by the viewer.
743    viewer.getUsage(*arguments.getApplicationUsage());
744
745    // read any time delay argument.
746    float timeDelayBetweenSlides = 5.0f;
747    while (arguments.read("-d",timeDelayBetweenSlides)) {}
748
749    bool autoSteppingActive = false;
750    while (arguments.read("-a")) autoSteppingActive = true;
751
752    // if user request help write it out to cout.
753    if (arguments.read("-h") || arguments.read("--help"))
754    {
755        arguments.getApplicationUsage()->write(std::cout);
756        return 1;
757    }
758
759    // any option left unread are converted into errors to write out later.
760    arguments.reportRemainingOptionsAsUnrecognized();
761
762    // report any errors if they have occured when parsing the program aguments.
763    if (arguments.errors())
764    {
765        arguments.writeErrorMessages(std::cout);
766        return 1;
767    }
768   
769    if (arguments.argc()<=1)
770    {
771        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
772        return 1;
773    }
774
775
776
777    // now the windows have been realized we switch off the cursor to prevent it
778    // distracting the people seeing the stereo images.
779    float fovx = 1.25f;
780    float fovy = 1.0f;
781    for( unsigned int i = 0; i < viewer.getCameraConfig()->getNumberOfCameras(); i++ )
782    {
783        Producer::Camera* cam = viewer.getCameraConfig()->getCamera(i);
784        Producer::RenderSurface* rs = cam->getRenderSurface();
785        //rs->useCursor(false);
786        fovx = cam->getLensHorizontalFov();
787        fovy = cam->getLensVerticalFov();
788    }
789
790    float radius = 1.0f;
791    float width = 2*radius*tan(fovx*0.5f);
792    float height = 2*radius*tan(fovy*0.5f);
793
794    osg::ref_ptr<Album> album = new Album(arguments,width,height);
795
796    // creat the scene from the file list.
797    osg::ref_ptr<osg::Group> rootNode = album->getScene();
798   
799    if (!rootNode) return 0;
800
801
802    //osgDB::writeNodeFile(*rootNode,"test.osg");
803
804    // set the scene to render
805    viewer.setSceneData(album->getScene());
806
807
808    // set up the SlideEventHandler.
809    seh->set(album.get(),timeDelayBetweenSlides,autoSteppingActive);
810   
811
812    // create the windows and run the threads.
813    viewer.realize();
814   
815    osg::Matrix homePosition;
816    homePosition.makeLookAt(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(0.0f,1.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f));
817       
818    while( !viewer.done() )
819    {
820        // wait for all cull and draw threads to complete.
821        viewer.sync();
822
823        // update the scene by traversing it with the the update visitor which will
824        // call all node update callbacks and animations.
825        viewer.update();
826         
827        //viewer.setView(homePosition);
828
829        // fire off the cull and draw traversals of the scene.
830        viewer.frame();
831       
832    }
833   
834    // wait for all cull and draw threads to complete before exit.
835    viewer.sync();
836   
837    return 0;
838}
Note: See TracBrowser for help on using the browser.