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

Revision 2566, 30.9 kB (checked in by robert, 10 years ago)

Added support for placing pictures of backs and fronts of pages.

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