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

Revision 13576, 23.4 kB (checked in by robert, 11 hours ago)

Added simple test script for osgUI's TabWidget?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[6941]1/* OpenSceneGraph example, osgphotoalbum.
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.
[2515]17*/
18
19#include <osg/Notify>
20#include <osg/MatrixTransform>
21#include <osg/Switch>
22#include <osg/PolygonOffset>
[2566]23#include <osg/CullFace>
[2515]24
[2566]25#include <osgUtil/Optimizer>
26
[2578]27#include <osgDB/FileNameUtils>
28
[2515]29#include <osgText/Text>
30
[5954]31#include <osgViewer/Viewer>
[2566]32
[2574]33#include "ImageReaderWriter.h"
[2515]34
[5954]35#include <iostream>
36
[2688]37using namespace osg;
38
[2574]39// now register with Registry to instantiate the above reader/writer,
40// declaring in main so that the code to set up PagedLOD can get a handle
[13576]41// to the ImageReaderWriter's
[2515]42osgDB::RegisterReaderWriterProxy<ImageReaderWriter> g_ImageReaderWriter;
43
[2539]44class Album;
[2515]45
[2539]46class Page : public osg::Transform
[2515]47{
48public:
49
[2539]50
[2566]51    static Page* createPage(Album* album, unsigned int pageNo, const std::string& frontFileName, const std::string& backFileName, float width, float height)
[2539]52    {
[2566]53        osg::ref_ptr<Page> page = new Page(album, pageNo, frontFileName, backFileName, width, height);
[2539]54        if (page.valid()) return page.release();
55        else return 0;
56    }
[13576]57
[2539]58    virtual void traverse(osg::NodeVisitor& nv);
[2515]59
[2539]60    void setRotation(float angle)
61    {
[13576]62        _rotation = angle;
63        _targetRotation = angle;
[2539]64        dirtyBound();
65    }
[2515]66
[2539]67    float getRotation() const { return _rotation; }
[2515]68
[2539]69    void rotateTo(float angle, float timeToRotateBy)
70    {
[13576]71        _targetRotation = angle;
[2539]72        _targetTime = timeToRotateBy;
73    }
[13576]74
[2539]75    bool rotating() const { return _targetRotation!=_rotation; }
[2515]76
[2566]77    void setPageVisible(bool frontVisible,bool backVisible)
78    {
79        _switch->setValue(0,!frontVisible && !backVisible);
80        _switch->setValue(1,frontVisible);
81        _switch->setValue(2,backVisible);
82    }
[2515]83
[2539]84    osg::Switch* getSwitch() { return _switch.get(); }
85    const osg::Switch* getSwitch() const { return _switch.get(); }
[2515]86
[2539]87public:
[2515]88
[13576]89    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
[2515]90    {
[3528]91        if (_referenceFrame==RELATIVE_RF)
[2515]92        {
[2539]93            matrix.preMult(getMatrix());
[2515]94        }
[2539]95        else // absolute
96        {
97            matrix = getMatrix();
98        }
99        return true;
[2515]100    }
101
[2539]102    /** Get the transformation matrix which moves from world coords to local coords.*/
103    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const
104    {
105        const osg::Matrix& inverse = getInverseMatrix();
[2515]106
[3528]107        if (_referenceFrame==RELATIVE_RF)
[2515]108        {
[2539]109            matrix.postMult(inverse);
[2515]110        }
[2539]111        else // absolute
[2515]112        {
[2539]113            matrix = inverse;
[2515]114        }
[2539]115        return true;
[2515]116    }
117
[2539]118    osg::Matrix getMatrix() const { return _pageOffset*osg::Matrix::rotate(-_rotation,0.0f,0.0f,1.0f); }
119    osg::Matrix getInverseMatrix() const { return osg::Matrix::inverse(getMatrix()); }
[2515]120
[2539]121protected:
[13576]122
[2566]123    Page(Album* album, unsigned int pageNo, const std::string& frontFileName, const std::string& backFileName, float width, float height);
[2515]124
[2539]125    float       _rotation;
126    osg::Matrix _pageOffset;
[2515]127
[2539]128    float       _targetRotation;
129    float       _targetTime;
130    float       _lastTimeTraverse;
[2515]131
[2539]132    osg::ref_ptr<osg::Switch>     _switch;
133
134};
135
136
137class Album : public osg::Referenced
[2515]138{
[2539]139public:
[2515]140
[2539]141    Album(osg::ArgumentParser& ap, float width, float height);
[2515]142
[2539]143    osg::Group* getScene() { return _group.get(); }
[13576]144
[2539]145    const osg::Group* getScene() const { return _group.get(); }
[2515]146
[2539]147    osg::Matrix getPageOffset(unsigned int pageNo) const;
[13576]148
[2539]149    bool nextPage(float timeToRotateBy) { return gotoPage(_currentPageNo+1,timeToRotateBy); }
150
151    bool previousPage(float timeToRotateBy) { return _currentPageNo>=1?gotoPage(_currentPageNo-1,timeToRotateBy):false; }
[13576]152
[2539]153    bool gotoPage(unsigned int pageNo, float timeToRotateBy);
[13576]154
[2539]155    osg::StateSet* getBackgroundStateSet() { return _backgroundStateSet.get(); }
[13576]156
[2539]157    void setVisibility();
158
159protected:
160
161    typedef std::vector< osg::ref_ptr<Page> > PageList;
162
163    osg::ref_ptr<osg::Group>    _group;
164    PageList                    _pages;
[13576]165
[2539]166    osg::ref_ptr<osg::StateSet> _backgroundStateSet;
[13576]167
[2539]168    unsigned int                _currentPageNo;
169    float                       _radiusOfRings;
170    float                       _startAngleOfPages;
[13576]171    float                       _deltaAngleBetweenPages;
[2539]172
173};
174
175
176////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177
178
[2566]179Page::Page(Album* album, unsigned int pageNo, const std::string& frontFileName, const std::string& backFileName, float width, float height)
[2515]180{
[2539]181    // set up transform parts.
182    _rotation = 0;
183    _targetRotation = 0;
184    _targetTime = 0;
185    _lastTimeTraverse = 0;
[13576]186
[2539]187    _pageOffset = album->getPageOffset(pageNo);
[13576]188
[2539]189    setNumChildrenRequiringUpdateTraversal(1);
[13576]190
191
[2539]192    // set up subgraph
[2515]193    osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal");
194    if (!readerWriter)
195    {
196        std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"<<std::endl;
197    }
198
[2539]199    _switch = new osg::Switch;
200
[2515]201    ImageReaderWriter* rw = g_ImageReaderWriter.get();
202
[13576]203
[2539]204    // set up non visible page.
205    osg::Group* non_visible_page = new osg::Group;
206    _switch->addChild(non_visible_page);
207    {
208        osg::Geometry* geom = new osg::Geometry;
209        geom->setStateSet(album->getBackgroundStateSet());
[2515]210
[13471]211        osg::Vec3Array* coords = new osg::Vec3Array(8);
212        (*coords)[0].set(0.0f,0.0f,0.0f);
213        (*coords)[1].set(0.0f,0.0f,height);
214        (*coords)[2].set(0.0f,0.0f,height);
215        (*coords)[3].set(width,0.0f,height);
216        (*coords)[4].set(width,0.0f,height);
217        (*coords)[5].set(width,0.0f,0.0f);
218        (*coords)[6].set(width,0.0f,0.0f);
219        (*coords)[7].set(0.0f,0.0f,0.0f);
[2539]220        geom->setVertexArray(coords);
[2515]221
[13576]222
[13471]223        osg::Vec3Array* normals = new osg::Vec3Array(8);
[2566]224        (*normals)[0].set(-1.0f,0.0f,0.0f);
[13471]225        (*normals)[1].set(-1.0f,0.0f,0.0f);
226        (*normals)[2].set(0.0f,0.0f,-1.0f);
227        (*normals)[3].set(0.0f,0.0f,-1.0f);
228        (*normals)[4].set(1.0f,0.0f,0.0f);
229        (*normals)[5].set(1.0f,0.0f,0.0f);
230        (*normals)[6].set(0.0f,0.0f,1.0f);
231        (*normals)[7].set(0.0f,0.0f,1.0f);
[13576]232        geom->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
[2539]233
[13471]234        osg::Vec2Array* tcoords = new osg::Vec2Array(8);
235        (*tcoords)[0].set(0.0f,0.0f);
236        (*tcoords)[1].set(0.0f,1.0f);
237        (*tcoords)[2].set(0.0f,1.0f);
[2539]238        (*tcoords)[3].set(1.0f,1.0f);
[13471]239        (*tcoords)[4].set(1.0f,1.0f);
240        (*tcoords)[5].set(0.0f,1.0f);
241        (*tcoords)[6].set(0.0f,1.0f);
242        (*tcoords)[7].set(0.0f,0.0f);
[2539]243        geom->setTexCoordArray(0,tcoords);
244
245        osg::Vec4Array* colours = new osg::Vec4Array(1);
246        (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
[13576]247        geom->setColorArray(colours, osg::Array::BIND_OVERALL);
[2539]248
[2566]249        geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,8));
250
[2539]251        // set up the geode.
252        osg::Geode* geode = new osg::Geode;
253        geode->addDrawable(geom);
[13576]254
255
[2539]256        non_visible_page->addChild(geode);
257    }
258
259
260    // set up visible page.
[2566]261    osg::Group* front_page = new osg::Group;
262    _switch->addChild(front_page);
[2539]263
[2515]264    {
[2539]265
266        osg::Geometry* geom = new osg::Geometry;
267        geom->setStateSet(album->getBackgroundStateSet());
268
269        osg::Vec3Array* coords = new osg::Vec3Array(4);
270        (*coords)[0].set(0.0f,0.0,height);
271        (*coords)[1].set(0.0f,0.0,0);
272        (*coords)[2].set(width,0.0,0);
273        (*coords)[3].set(width,0.0,height);
274        geom->setVertexArray(coords);
275
276        osg::Vec3Array* normals = new osg::Vec3Array(1);
277        (*normals)[0].set(0.0f,-1.0f,0.0f);
[13576]278        geom->setNormalArray(normals, osg::Array::BIND_OVERALL);
[2539]279
280        osg::Vec2Array* tcoords = new osg::Vec2Array(4);
281        (*tcoords)[0].set(0.0f,1.0f);
282        (*tcoords)[1].set(0.0f,0.0f);
283        (*tcoords)[2].set(1.0f,0.0f);
284        (*tcoords)[3].set(1.0f,1.0f);
285        geom->setTexCoordArray(0,tcoords);
286
287        osg::Vec4Array* colours = new osg::Vec4Array(1);
288        (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
[13576]289        geom->setColorArray(colours, osg::Array::BIND_OVERALL);
[2539]290
291        geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
292
293        // set up the geode.
294        osg::Geode* geode = new osg::Geode;
295        geode->addDrawable(geom);
[13576]296
297
[2566]298        front_page->addChild(geode);
[2539]299    }
300
[2566]301    if (!frontFileName.empty())
[2539]302    {
[2515]303        float cut_off_distance = 8.0f;
304        float max_visible_distance = 300.0f;
[13576]305
[2539]306        osg::Vec3 center(width*0.5f,0.0f,height*0.5f);
[2515]307
308        osgText::Text* text = new osgText::Text;
309        text->setFont("fonts/arial.ttf");
310        text->setPosition(center);
[2539]311        text->setCharacterSize(height/20.0f);
[2515]312        text->setAlignment(osgText::Text::CENTER_CENTER);
313        text->setAxisAlignment(osgText::Text::XZ_PLANE);
[2539]314        text->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
[2566]315        text->setText(std::string("Loading ")+frontFileName);
[2515]316
317        osg::Geode* geode = new osg::Geode;
318        geode->addDrawable(text);
[13576]319
[2515]320        osg::PagedLOD* pagedlod = new osg::PagedLOD;
321        pagedlod->setCenter(center);
322        pagedlod->setRadius(1.6f);
323        pagedlod->setNumChildrenThatCannotBeExpired(2);
[13576]324
[2515]325        pagedlod->setRange(0,max_visible_distance,1e7);
326        pagedlod->addChild(geode);
[13576]327
[2515]328        pagedlod->setRange(1,cut_off_distance,max_visible_distance);
[2566]329        pagedlod->setFileName(1,rw->insertReference(frontFileName,256,width,height,false));
[2515]330
331        pagedlod->setRange(2,0.0f,cut_off_distance);
[2566]332        pagedlod->setFileName(2,rw->insertReference(frontFileName,1024,width,height,false));
[2515]333
[2566]334        front_page->addChild(pagedlod);
[2515]335    }
[13576]336
337
[2566]338    // set up back of page.
339    osg::Group* back_page = new osg::Group;
340    _switch->addChild(back_page);
341
342    {
343
344        osg::Geometry* geom = new osg::Geometry;
345        geom->setStateSet(album->getBackgroundStateSet());
346
347        osg::Vec3Array* coords = new osg::Vec3Array(4);
348        (*coords)[0].set(width,0.0,height);
349        (*coords)[1].set(width,0.0,0);
350        (*coords)[2].set(0.0f,0.0,0);
351        (*coords)[3].set(0.0f,0.0,height);
352        geom->setVertexArray(coords);
353
354        osg::Vec3Array* normals = new osg::Vec3Array(1);
355        (*normals)[0].set(0.0f,1.0f,0.0f);
[13576]356        geom->setNormalArray(normals, osg::Array::BIND_OVERALL);
[2566]357
358        osg::Vec2Array* tcoords = new osg::Vec2Array(4);
359        (*tcoords)[0].set(1.0f,1.0f);
360        (*tcoords)[1].set(1.0f,0.0f);
361        (*tcoords)[2].set(0.0f,0.0f);
362        (*tcoords)[3].set(0.0f,1.0f);
363        geom->setTexCoordArray(0,tcoords);
364
365        osg::Vec4Array* colours = new osg::Vec4Array(1);
366        (*colours)[0].set(1.0f,1.0f,1.0,1.0f);
[13576]367        geom->setColorArray(colours, osg::Array::BIND_OVERALL);
[2566]368
369        geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
370
371        // set up the geode.
372        osg::Geode* geode = new osg::Geode;
373        geode->addDrawable(geom);
[13576]374
375
[2566]376        back_page->addChild(geode);
377    }
378
379    if (!backFileName.empty())
380    {
381        float cut_off_distance = 8.0f;
382        float max_visible_distance = 300.0f;
[13576]383
[2566]384        osg::Vec3 center(width*0.5f,0.0f,height*0.5f);
385
386        osgText::Text* text = new osgText::Text;
387        text->setFont("fonts/arial.ttf");
388        text->setPosition(center);
389        text->setCharacterSize(height/20.0f);
390        text->setAlignment(osgText::Text::CENTER_CENTER);
391        text->setAxisAlignment(osgText::Text::REVERSED_XZ_PLANE);
392        text->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
393        text->setText(std::string("Loading ")+backFileName);
394
395        osg::Geode* geode = new osg::Geode;
396        geode->addDrawable(text);
[13576]397
[2566]398        osg::PagedLOD* pagedlod = new osg::PagedLOD;
399        pagedlod->setCenter(center);
400        pagedlod->setRadius(1.6f);
401        pagedlod->setNumChildrenThatCannotBeExpired(2);
[13576]402
[2566]403        pagedlod->setRange(0,max_visible_distance,1e7);
404        pagedlod->addChild(geode);
[13576]405
[2566]406        pagedlod->setRange(1,cut_off_distance,max_visible_distance);
407        pagedlod->setFileName(1,rw->insertReference(backFileName,256,width,height,true));
408
409        pagedlod->setRange(2,0.0f,cut_off_distance);
410        pagedlod->setFileName(2,rw->insertReference(backFileName,1024,width,height,true));
411
412        back_page->addChild(pagedlod);
413    }
414
[2539]415    addChild(_switch.get());
416}
[2515]417
[2539]418void Page::traverse(osg::NodeVisitor& nv)
419{
420    // if app traversal update the frame count.
421    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
422    {
423        const osg::FrameStamp* framestamp = nv.getFrameStamp();
424        if (framestamp)
425        {
[6051]426            double t = framestamp->getSimulationTime();
[13576]427
[2539]428            if (_rotation!=_targetRotation)
429            {
430                if (t>=_targetTime) _rotation = _targetRotation;
431                else _rotation += (_targetRotation-_rotation)*(t-_lastTimeTraverse)/(_targetTime-_lastTimeTraverse);
[13576]432
[2539]433                dirtyBound();
434            }
[13576]435
[2539]436            _lastTimeTraverse = t;
[2515]437
[2539]438        }
439    }
440    Transform::traverse(nv);
441}
442
443
444////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
445
446Album::Album(osg::ArgumentParser& arguments, float width, float height)
447{
448
449
450    typedef std::vector<std::string> FileList;
451    FileList fileList;
452
453    for(int pos=1;pos<arguments.argc();++pos)
454    {
[13576]455        if (arguments.isString(pos))
[2578]456        {
457            std::string filename(arguments[pos]);
458            if (osgDB::getLowerCaseFileExtension(filename)=="album")
459            {
460                PhotoArchive* photoArchive = PhotoArchive::open(filename);
461                if (photoArchive)
462                {
463                    g_ImageReaderWriter.get()->addPhotoArchive(photoArchive);
464                    photoArchive->getImageFileNameList(fileList);
465                }
[13576]466
[2578]467            }
468            else
469            {
470                fileList.push_back(arguments[pos]);
471            }
472        }
[2539]473    }
[13576]474
[2539]475    _radiusOfRings = 0.02;
476    _startAngleOfPages = 0.0f;
477    _deltaAngleBetweenPages = osg::PI/(float)fileList.size();
[13576]478
[2539]479    _group = new osg::Group;
[2566]480    _group->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace,osg::StateAttribute::ON);
[13576]481
[2539]482    _backgroundStateSet = new osg::StateSet;
483    _backgroundStateSet->setAttributeAndModes(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON);
[13576]484
[2539]485    // load the images.
486    unsigned int i;
[2566]487    for(i=0;i<fileList.size();i+=2)
[2539]488    {
[2566]489        Page* page = i+1<fileList.size()?
490                     Page::createPage(this,_pages.size(),fileList[i],fileList[i+1], width, height):
491                     Page::createPage(this,_pages.size(),fileList[i],"", width, height);
[2539]492        if (page)
493        {
494            _pages.push_back(page);
495            _group->addChild(page);
496        }
497    }
[13576]498
[2539]499    setVisibility();
[2515]500
[2539]501}
502
503osg::Matrix Album::getPageOffset(unsigned int pageNo) const
504{
505    float angleForPage = _startAngleOfPages+_deltaAngleBetweenPages*(float)pageNo;
506    osg::Vec3 delta(_radiusOfRings*sinf(angleForPage),-_radiusOfRings*cosf(angleForPage),0.0f);
507    return osg::Matrix::translate(delta);
508}
509
510bool Album::gotoPage(unsigned int pageNo, float timeToRotateBy)
511{
512    if (pageNo>=_pages.size()) return false;
513
514    if (pageNo>_currentPageNo)
[2515]515    {
[2539]516        for(unsigned int i=_currentPageNo;i<pageNo;++i)
517        {
518            _pages[i]->rotateTo(osg::PI,timeToRotateBy);
519        }
520        _currentPageNo = pageNo;
[13576]521
[2539]522        return true;
[2515]523    }
[2539]524    else if (pageNo<_currentPageNo)
[2515]525    {
[2539]526        for(unsigned int i=pageNo;i<_currentPageNo;++i)
[2515]527        {
[2539]528            _pages[i]->rotateTo(0,timeToRotateBy);
[2515]529        }
[2539]530        _currentPageNo = pageNo;
[13576]531
[2539]532        return true;
[2515]533    }
[13576]534
[2539]535    return false;
536}
537
538void Album::setVisibility()
539{
540    for(unsigned int i=0;i<_pages.size();++i)
[2515]541    {
[2566]542        bool front_visible = _pages[i]->rotating() ||
543                             (i>0?_pages[i-1]->rotating():false) ||
544                             i==_currentPageNo ||
545                             i==0;
546
547        bool back_visible = _pages[i]->rotating() ||
548                            ((i+1)<_pages.size()?_pages[i+1]->rotating():false) ||
549                            i==_currentPageNo-1 ||
550                            i==_pages.size()-1;
[13576]551
[2566]552        _pages[i]->setPageVisible(front_visible,back_visible);
[2515]553    }
[13576]554
[2539]555}
[2515]556
[2539]557
558////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
559
560
561class SlideEventHandler : public osgGA::GUIEventHandler
562{
563public:
564
565    SlideEventHandler();
[13576]566
[2539]567    META_Object(osgStereImageApp,SlideEventHandler);
568
569    void set(Album* album, float timePerSlide, bool autoSteppingActive);
570
571    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
[13576]572
[2539]573    virtual void getUsage(osg::ApplicationUsage& usage) const;
574
575protected:
576
577    ~SlideEventHandler() {}
578    SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {}
579
580    osg::ref_ptr<Album>         _album;
581    bool                        _firstTraversal;
582    double                      _previousTime;
583    double                      _timePerSlide;
584    bool                        _autoSteppingActive;
585};
586
587SlideEventHandler::SlideEventHandler():
588    _album(0),
589    _firstTraversal(true),
590    _previousTime(-1.0f),
591    _timePerSlide(5.0),
592    _autoSteppingActive(false)
593{
594}
595
596void SlideEventHandler::set(Album* album, float timePerSlide, bool autoSteppingActive)
597{
598    _album = album;
599
600    _timePerSlide = timePerSlide;
[13576]601    _autoSteppingActive = autoSteppingActive;
602
[2539]603}
604
605bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
606{
607    switch(ea.getEventType())
[2515]608    {
[2539]609        case(osgGA::GUIEventAdapter::KEYDOWN):
610        {
611            if (ea.getKey()=='a')
612            {
613                _autoSteppingActive = !_autoSteppingActive;
[5032]614                _previousTime = ea.getTime();
[2539]615                return true;
616            }
617            else if (ea.getKey()=='n')
618            {
[5032]619                _album->nextPage(ea.getTime()+1.0f);
[2539]620                return true;
621            }
622            else if (ea.getKey()=='p')
623            {
[5032]624                _album->previousPage(ea.getTime()+1.0f);
[2539]625                return true;
626            }
627            return false;
628        }
629        case(osgGA::GUIEventAdapter::FRAME):
630        {
631            if (_autoSteppingActive)
632            {
633                if (_firstTraversal)
634                {
635                    _firstTraversal = false;
[5032]636                    _previousTime = ea.getTime();
[2539]637                }
[5032]638                else if (ea.getTime()-_previousTime>_timePerSlide)
[2539]639                {
[5032]640                    _previousTime = ea.getTime();
[2539]641
[5032]642                    _album->nextPage(ea.getTime()+1.0f);
[2539]643                }
644            }
[13576]645
[2539]646            _album->setVisibility();
647
648        }
649
650        default:
651            return false;
[2515]652    }
[2539]653}
[2515]654
[2539]655void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const
656{
657    usage.addKeyboardMouseBinding("Space","Reset the image position to center");
658    usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image");
659    usage.addKeyboardMouseBinding("n","Advance to next image");
660    usage.addKeyboardMouseBinding("p","Move to previous image");
[2515]661}
662
663int main( int argc, char **argv )
664{
665
666    // use an ArgumentParser object to manage the program arguments.
667    osg::ArgumentParser arguments(&argc,argv);
[13576]668
[2515]669    // set up the usage document, in case we need to print out how to use this program.
670    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
671    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file [image_file]");
[7648]672    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in seconds between the display of successive image pairs when in auto advance mode.");
[2515]673    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
674    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
[2578]675    arguments.getApplicationUsage()->addCommandLineOption("--create <filename>","Create an photo archive of specified files");
[2515]676
[13576]677
[2515]678    // construct the viewer.
[7565]679    osgViewer::Viewer viewer(arguments);
[13576]680
[7565]681    viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
[2515]682
[7648]683    // register the handler to add keyboard and mouse handling.
[2515]684    SlideEventHandler* seh = new SlideEventHandler();
[5954]685    viewer.addEventHandler(seh);
[2515]686
687    // read any time delay argument.
688    float timeDelayBetweenSlides = 5.0f;
689    while (arguments.read("-d",timeDelayBetweenSlides)) {}
690
691    bool autoSteppingActive = false;
692    while (arguments.read("-a")) autoSteppingActive = true;
693
694    // if user request help write it out to cout.
695    if (arguments.read("-h") || arguments.read("--help"))
696    {
697        arguments.getApplicationUsage()->write(std::cout);
698        return 1;
699    }
700
[2578]701    std::string archiveName;
702    while (arguments.read("--create",archiveName)) {}
[13576]703
[2515]704    // any option left unread are converted into errors to write out later.
705    arguments.reportRemainingOptionsAsUnrecognized();
706
[7648]707    // report any errors if they have occurred when parsing the program arguments.
[2515]708    if (arguments.errors())
709    {
710        arguments.writeErrorMessages(std::cout);
711        return 1;
712    }
[13576]713
[2515]714    if (arguments.argc()<=1)
715    {
716        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
717        return 1;
718    }
719
720
[2578]721    if (!archiveName.empty())
722    {
723        // archive name set to create
724        PhotoArchive::FileNameList fileNameList;
725        for(int i=1;i<arguments.argc();++i)
726        {
727            if (arguments.isString(i)) fileNameList.push_back(std::string(arguments[i]));
728        }
[13576]729
[2578]730        PhotoArchive::buildArchive(archiveName,fileNameList);
[13576]731
[2578]732        return 0;
733    }
[2515]734
[2578]735
[2515]736    // now the windows have been realized we switch off the cursor to prevent it
737    // distracting the people seeing the stereo images.
[5954]738    double fovy, aspectRatio, zNear, zFar;
739    viewer.getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
[2515]740
[5954]741    fovy = osg::DegreesToRadians(fovy);
742    double fovx = atan(tan(fovy*0.5)*aspectRatio)*2.0;
[13576]743
[2515]744    float radius = 1.0f;
[2539]745    float width = 2*radius*tan(fovx*0.5f);
[2515]746    float height = 2*radius*tan(fovy*0.5f);
747
[2539]748    osg::ref_ptr<Album> album = new Album(arguments,width,height);
749
[2515]750    // creat the scene from the file list.
[2539]751    osg::ref_ptr<osg::Group> rootNode = album->getScene();
[13576]752
[2515]753    if (!rootNode) return 0;
754
755
[12529]756    //osgDB::writeNodeFile(*rootNode,"test.osgt");
[2515]757
758    // set the scene to render
[2539]759    viewer.setSceneData(album->getScene());
[2515]760
761    // set up the SlideEventHandler.
[2539]762    seh->set(album.get(),timeDelayBetweenSlides,autoSteppingActive);
[13576]763
[2515]764    viewer.realize();
[13576]765
[5954]766    // switch off the cursor
767    osgViewer::Viewer::Windows windows;
768    viewer.getWindows(windows);
769    for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
770        itr != windows.end();
771        ++itr)
[2515]772    {
[5954]773        (*itr)->useCursor(false);
[2515]774    }
[5381]775
776
[5954]777    return viewer.run();
[2515]778}
Note: See TracBrowser for help on using the browser.