root/OpenSceneGraph/trunk/examples/osgcatch/osgcatch.cpp @ 5636

Revision 5636, 48.1 kB (checked in by robert, 8 years ago)

Removed deprecated GUIEventHandler method

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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
18#include <osgUtil/Optimizer>
19#include <osgUtil/GLObjectsVisitor>
20
21#include <osgText/Text>
22
23#include <osg/Geode>
24#include <osg/Notify>
25#include <osg/MatrixTransform>
26#include <osg/PositionAttitudeTransform>
27#include <osg/Switch>
28#include <osg/TexMat>
29#include <osg/Texture2D>
30#include <osg/io_utils>
31
32#include <osgParticle/ExplosionEffect>
33#include <osgParticle/ExplosionDebrisEffect>
34#include <osgParticle/SmokeEffect>
35#include <osgParticle/FireEffect>
36
37#include <sstream>
38
39typedef std::vector<std::string> FileList;
40typedef std::map<std::string, osg::ref_ptr<osg::Node> >  ObjectMap;
41
42static ObjectMap    s_objectMap;
43
44class Character : public osg::Referenced
45{
46public:
47    Character();
48   
49    void setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& orgin, const osg::Vec3& width, const osg::Vec3& catchPos, float positionRatio);
50   
51    void setLives(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives);
52   
53    void setCatches(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives);
54
55    void moveLeft();
56    void moveRight();
57    void moveTo(float positionRatio);
58
59    void reset();
60
61    void resetCatches();
62
63    bool addCatch();
64   
65    bool looseLife();
66
67    osg::Vec3 getCurrentCenterOfBasket() const { return _character->getPosition()+_centerBasket; }
68    float getCurrentRadiusOfBasket() const { return _radiusBasket; }
69
70    osg::Vec3 getLowerLeft() const { return _character->getPosition(); }
71    osg::Vec3 getUpperRight() const { return _character->getPosition(); }
72
73    osg::Vec3 _origin;
74    osg::Vec3 _width;
75
76    float                                        _positionRatio;
77    osg::ref_ptr<osg::PositionAttitudeTransform> _character;
78
79    unsigned int                                 _numLives;
80    osg::ref_ptr<osg::Switch>                    _livesSwitch;
81
82    unsigned int                                 _numCatches;
83    osg::ref_ptr<osg::Switch>                    _catchSwitch;
84   
85    osg::ref_ptr<osg::Group>                     _objectsGroup;
86   
87    osg::Vec3                                    _centerBasket;
88    float                                        _radiusBasket;
89   
90};
91
92Character::Character():
93    _positionRatio(0.5f),
94    _numLives(3),
95    _numCatches(0)
96{
97}
98
99
100void Character::setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& origin, const osg::Vec3& width, const osg::Vec3& catchPos, float positionRatio)
101{
102    _origin = origin;
103    _width = width;
104    _positionRatio = positionRatio;
105    _numLives = 3;
106    _numCatches = 0;
107
108    float _characterSize = _width.length()*0.2f;
109
110    osg::Image* image = osgDB::readImageFile(filename);
111    if (image)
112    {
113        osg::Vec3 pos(-0.5f*_characterSize,0.0f,0.0f);
114        osg::Vec3 width(_characterSize*((float)image->s())/(float)(image->t()),0.0f,0.0);
115        osg::Vec3 height(0.0f,0.0f,_characterSize);
116
117        osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
118        osg::StateSet* stateset = geometry->getOrCreateStateSet();
119        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
120        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
121        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
122
123        osg::Geode* geode = new osg::Geode;
124        geode->addDrawable(geometry);
125
126        _character = new osg::PositionAttitudeTransform;
127        _character->setName(name);
128        _character->addChild(geode);
129       
130        moveTo(positionRatio);
131
132        _centerBasket = width*catchPos.x() + height*catchPos.y() + pos;
133        _radiusBasket = width.length()*catchPos.z();
134
135    }
136   
137}
138
139void Character::setLives(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numLives)
140{
141    float characterSize = delta.length();
142
143    _numLives = numLives;
144    _livesSwitch = new osg::Switch;
145
146    osg::Image* image = osgDB::readImageFile(filename);
147    if (image)
148    {
149        osg::StateSet* stateset = _livesSwitch->getOrCreateStateSet();
150        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
151        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
152        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
153
154        for(unsigned int i=0; i<numLives; ++i)
155        {
156            osg::Vec3 pos = origin + delta*(float)i + osg::Vec3(0.0f,0.0f,0.0f);
157            osg::Vec3 width(characterSize*((float)image->s())/(float)(image->t()),0.0f,0.0);
158            osg::Vec3 height(0.0f,0.0f,characterSize);
159
160            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
161
162            osg::Geode* geode = new osg::Geode;
163            geode->addDrawable(geometry);
164
165            _livesSwitch->addChild(geode,true);
166
167        }
168    }
169
170}
171
172void Character::setCatches(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numCatches)
173{
174    float characterSize = delta.length();
175
176    _numCatches = 0;
177    _catchSwitch = new osg::Switch;
178
179    osg::Image* image = osgDB::readImageFile(filename);
180    if (image)
181    {
182        osg::StateSet* stateset = _catchSwitch->getOrCreateStateSet();
183        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
184        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
185        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
186
187        for(unsigned int i=0; i<numCatches; ++i)
188        {
189            osg::Vec3 pos = origin + delta*(float)i + osg::Vec3(0.0f,0.0f,0.0f);
190            osg::Vec3 width(characterSize,0.0f,0.0);
191            osg::Vec3 height(0.0f,0.0f,characterSize*((float)image->t())/(float)(image->s()));
192
193            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
194
195            osg::Geode* geode = new osg::Geode;
196            geode->addDrawable(geometry);
197
198            _catchSwitch->addChild(geode,false);
199
200        }
201    }
202
203}
204
205void Character::moveLeft()
206{
207    moveTo(_positionRatio - 0.01f);
208}
209
210void Character::moveRight()
211{
212    moveTo(_positionRatio + 0.01f);
213}
214
215void Character::moveTo(float positionRatio)
216{
217    if (positionRatio<0.0f) positionRatio = 0.0f;
218    if (positionRatio>1.0f) positionRatio = 1.0f;
219
220    _positionRatio = positionRatio;
221    _character->setPosition(_origin+_width*+positionRatio);
222}
223
224void Character::reset()
225{
226    _numCatches = 0;
227    _numLives = _livesSwitch->getNumChildren();
228
229    _livesSwitch->setAllChildrenOn();
230    _catchSwitch->setAllChildrenOff();
231}
232
233void Character::resetCatches()
234{
235    _numCatches = 0;
236    _catchSwitch->setAllChildrenOff();
237}
238
239bool Character::addCatch()
240{
241    if (!_catchSwitch || _numCatches>=_catchSwitch->getNumChildren()) return false;
242   
243    _catchSwitch->setValue(_numCatches,true);
244    ++_numCatches;
245   
246    return true;
247}
248
249bool Character::looseLife()
250{
251    if (!_livesSwitch || _numLives==0) return false;
252   
253    --_numLives;
254    _livesSwitch->setValue(_numLives,false);
255   
256    return (_numLives!=0);
257}
258
259
260//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
261//
262class CatchableObject  : public osg::Referenced
263{
264    public:
265        CatchableObject();
266
267        void setObject(const std::string& filename, const std::string& name, const osg::Vec3& center, float size, const osg::Vec3& direction);
268
269        bool anyInside(const osg::Vec3& lower_left, const osg::Vec3& top_right);
270
271        bool centerInside(const osg::Vec3& center, float radius);
272       
273        void explode();
274       
275        bool dangerous() { return _dangerous; }
276
277        void stop() { _stopped = true; }
278       
279        bool stopped() { return _stopped; }
280       
281        void setTimeToRemove(double time) { _timeToRemove=time; }
282       
283        double getTimeToRemove() { return _timeToRemove; }
284       
285        bool needToRemove(double time) { return  _timeToRemove>=0.0 && time>_timeToRemove; }
286       
287        osg::ref_ptr<osg::PositionAttitudeTransform> _object;
288        osg::Vec3                                    _velocity;
289        float                                        _mass;
290        float                                        _radius;
291
292        bool                                         _stopped;
293        bool                                         _dangerous;
294
295        double                                       _timeToRemove;
296
297        static void setUpCatchablesMap(const FileList& fileList);
298
299    public:
300   
301        // update position and velocity
302        void update(double dt);
303
304        /// Set the viscosity of the fluid.
305        inline void setFluidViscosity(float v)
306        {
307            _viscosity = v;
308            _viscosityCoefficient = 6 * osg::PI * _viscosity;
309        }
310       
311        /// Get the viscosity of the fluid.
312        inline float getFluidViscosity() const { return _viscosity; }
313
314        /// Set the density of the fluid.
315        inline void setFluidDensity(float d)
316        {
317            _density = d;
318            _densityCoefficeint = 0.2f * osg::PI * _density;
319        }
320
321        /// Get the density of the fluid.
322        inline float getFluidDensity() const { return _density; }
323       
324       
325        /// Set the wind vector.
326        inline void setWind(const osg::Vec3& wind) { _wind = wind; }
327       
328        /// Get the wind vector.
329        inline const osg::Vec3& getWind() const { return _wind; }
330       
331        /// Set the acceleration vector.
332        inline void setAcceleration(const osg::Vec3& v) { _acceleration = v; }
333       
334        /// Get the acceleration vector.
335        inline const osg::Vec3& getAcceleration() const { return _acceleration; }
336
337        /** Set the acceleration vector to the gravity on earth (0, 0, -9.81).
338            The acceleration will be multiplied by the <CODE>scale</CODE> parameter.
339        */
340        inline void setToGravity(float scale = 1.0f) { _acceleration.set(0, 0, -9.81f*scale); }
341
342        /// Set the fluid parameters as for air (20°C temperature).
343        inline void setFluidToAir()
344        {
345            setToGravity(1.0f);
346            setFluidDensity(1.2929f);
347            setFluidViscosity(1.8e-5f);
348        }
349       
350        /// Set the fluid parameters as for pure water (20°C temperature).
351        inline void setFluidToWater()
352        {
353            setToGravity(1.0f);
354            setFluidDensity(1.0f);
355            setFluidViscosity(1.002e-3f);
356        }
357           
358
359    protected:
360
361        osg::Vec3   _acceleration;
362        float       _viscosity;
363        float       _density;
364        osg::Vec3   _wind;
365
366        float       _viscosityCoefficient;
367        float       _densityCoefficeint;
368       
369 
370};
371
372CatchableObject::CatchableObject()
373{
374    _stopped = false;
375    _dangerous = false;
376   
377    _timeToRemove = -1.0; // do not remove.
378    setFluidToAir();
379}
380
381void CatchableObject::setUpCatchablesMap(const FileList& fileList)
382{
383    for(FileList::const_iterator itr=fileList.begin();
384        itr!=fileList.end();
385        ++itr)
386    {
387        const std::string& filename = *itr;
388        osg::Image* image = osgDB::readImageFile(filename);
389        if (image)
390        {
391            osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
392            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
393            stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
394            stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
395           
396            osg::Vec3 width((float)(image->s())/(float)(image->t()),0.0f,0.0);
397            osg::Vec3 height(0.0f,0.0f,1.0f);
398            osg::Vec3 pos = (width+height)*-0.5f;
399
400            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
401            geometry->setStateSet(stateset.get());
402
403            osg::Geode* geode = new osg::Geode;
404            geode->addDrawable(geometry);
405
406            s_objectMap[filename] = geode;
407        }
408    }
409}
410
411void CatchableObject::setObject(const std::string& filename, const std::string& name, const osg::Vec3& center, float characterSize, const osg::Vec3& velocity)
412{
413    _radius = 0.5f*characterSize;
414    float Area = osg::PI*_radius*_radius;
415    float Volume = Area*_radius*4.0f/3.0f;
416
417    _velocity = velocity;
418    _mass = 1000.0*Volume;
419
420    if (s_objectMap.count(filename)!=0)
421    {
422        osg::PositionAttitudeTransform* scaleTransform = new osg::PositionAttitudeTransform;
423        scaleTransform->setScale(osg::Vec3(characterSize,characterSize,characterSize));
424        scaleTransform->addChild(s_objectMap[filename].get());
425
426        _object = new osg::PositionAttitudeTransform;
427        _object->setName(name);
428        _object->setPosition(center);
429        _object->addChild(scaleTransform);
430    }
431    else
432    {
433        osg::notify(osg::NOTICE)<<"CatchableObject::setObject("<<filename<<") not able to create catchable object."<<std::endl;
434    }
435}
436
437void CatchableObject::update(double dt)
438{
439    if (_stopped) return;
440
441    float Area = osg::PI*_radius*_radius;
442    float Volume = Area*_radius*4.0f/3.0f;
443
444    // compute force due to gravity + boyancy of displacing the fluid that the particle is emersed in.
445    osg::Vec3 force = _acceleration * (_mass - _density*Volume);
446
447    // compute force due to friction
448    osg::Vec3 relative_wind = _velocity-_wind;           
449    force -= relative_wind * Area * (_viscosityCoefficient + _densityCoefficeint*relative_wind.length());           
450
451    // divide force by mass to get acceleration.
452    _velocity += force*(dt/_mass);
453    _object->setPosition(_object->getPosition()+_velocity*dt);
454}
455
456bool CatchableObject::anyInside(const osg::Vec3& lower_left, const osg::Vec3& upper_right)
457{
458    osg::Vec3 pos = _object->getPosition();
459   
460    if (pos.x()+_radius < lower_left.x()) return false;
461    if (pos.x()-_radius > upper_right.x()) return false;
462    if (pos.z()+_radius < lower_left.z()) return false;
463    if (pos.z()-_radius > upper_right.z()) return false;
464
465    return true;
466}
467
468bool CatchableObject::centerInside(const osg::Vec3& center, float radius)
469{
470    osg::Vec3 delta = _object->getPosition() - center;
471    return (delta.length()<radius);
472}
473
474
475void CatchableObject::explode()
476{
477    osg::Vec3 position(0.0f,0.0f,0.0f);
478    osgParticle::ExplosionEffect* explosion = new osgParticle::ExplosionEffect(position, _radius);
479    osgParticle::ExplosionDebrisEffect* explosionDebri = new osgParticle::ExplosionDebrisEffect(position, _radius);
480    osgParticle::SmokeEffect* smoke = new osgParticle::SmokeEffect(position, _radius);
481    osgParticle::FireEffect* fire = new osgParticle::FireEffect(position, _radius);
482
483    explosion->setWind(_wind);
484    explosionDebri->setWind(_wind);
485    smoke->setWind(_wind);
486    fire->setWind(_wind);
487
488    _object->addChild(explosion);
489    _object->addChild(explosionDebri);
490    _object->addChild(smoke);
491    _object->addChild(fire);
492
493    _dangerous = true;
494
495}
496
497
498
499//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
500//
501class GameEventHandler : public osgGA::GUIEventHandler
502{
503public:
504
505    GameEventHandler();
506   
507    META_Object(osgStereImageApp,GameEventHandler);
508
509    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
510   
511    virtual void getUsage(osg::ApplicationUsage& usage) const;
512   
513    osg::Matrix getCameraPosition();
514   
515    void compileGLObjects(osg::State& state)
516    {
517        osgUtil::GLObjectsVisitor compile;
518        compile.setState(&state);
519   
520        for(ObjectMap::iterator itr = s_objectMap.begin();
521            itr != s_objectMap.end();
522            ++itr)
523        {
524            itr->second->accept(compile);
525        }
526    }
527   
528    osg::Node* createScene();
529   
530    void setFOVY(float fovy) { _fovy = fovy; }
531    float getFOVY() const { return _fovy; }
532   
533    void createNewCatchable();
534   
535    void clearCatchables()
536    {
537        for(CatchableObjectList::iterator itr=_catchableObjects.begin();
538            itr!=_catchableObjects.end();
539            ++itr)
540        {
541            // need to remove
542            // remove child from parents.
543            osg::ref_ptr<osg::PositionAttitudeTransform> child = (*itr)->_object;
544            osg::Node::ParentList parents = child->getParents();
545            for(osg::Node::ParentList::iterator pitr=parents.begin();
546                pitr!=parents.end();
547                ++pitr)
548            {
549                (*pitr)->removeChild(child.get());
550            }
551        }
552
553        _catchableObjects.clear();
554    }
555   
556    void resetLevel()
557    {
558        _level = 0;
559        _levelSwitch->setSingleChildOn(_level);
560        clearCatchables();
561
562        updateLevelText();
563
564        _levelStartTick = osg::Timer::instance()->tick();
565    }
566   
567    void nextLevel()
568    {
569        ++_level;
570        if (_level < _levelSwitch->getNumChildren())
571        {
572            _levelSwitch->setSingleChildOn(_level);
573            clearCatchables();
574        }
575
576        updateLevelText();
577
578        _levelStartTick = osg::Timer::instance()->tick();
579    }
580
581    bool gameComplete()
582    {
583        return _level >= _levelSwitch->getNumChildren();
584    }
585
586    void resetGame()
587    {
588        _currentScore = 0;
589       
590        updateTextWithScore();
591
592        clearCatchables();
593        resetLevel();
594       
595        for(unsigned int i=0;i<_numberOfPlayers;++i)
596        {
597            _players[i].reset();
598        }
599    }
600
601
602    enum Players
603    {
604        PLAYER_GIRL,
605        PLAYER_BOY
606    };
607
608    void addPlayer(Players player)
609    {
610        osg::Vec3 livesPosition;
611        osg::Vec3 catchesPosition;
612        if (_numberOfPlayers==0)
613        {
614            livesPosition = _originBaseLine+osg::Vec3(0.0f,-0.5f,0.0f);
615            catchesPosition = _originBaseLine+osg::Vec3(100.0f,-0.5f,0.0f);
616        }
617        else
618        {
619            livesPosition = _originBaseLine+osg::Vec3(1000.0f,-0.5f,000.0f);
620            catchesPosition = _originBaseLine+osg::Vec3(1100.0f,-0.5f,0.0f);
621        }
622       
623        switch(player)
624        {
625            case PLAYER_GIRL:
626            {
627                std::string player_one = "Catch/girl.png";
628                osg::Vec3 catchPos(0.2, 0.57, 0.34);
629
630                _players[_numberOfPlayers].setCharacter(player_one,"girl", _originBaseLine + osg::Vec3(0.0f,-1.0f,0.0f), _widthBaseLine, catchPos, 0.5f);
631                _players[_numberOfPlayers].setLives(player_one,livesPosition, osg::Vec3(0.0f,0.0f,100.0f),3);
632                _players[_numberOfPlayers].setCatches("Catch/broach.png",catchesPosition, osg::Vec3(0.0f,0.0f,100.0f),10);
633
634                ++_numberOfPlayers;
635                break;
636            }
637            case PLAYER_BOY:
638            {
639                std::string player_two = "Catch/boy.png";
640                osg::Vec3 catchPos(0.8, 0.57, 0.34);
641
642                _players[_numberOfPlayers].setCharacter(player_two,"boy", _originBaseLine + osg::Vec3(0.0f,-2.0f,0.0f), _widthBaseLine, catchPos, 0.5f);
643                _players[_numberOfPlayers].setLives(player_two,livesPosition, osg::Vec3(0.0f,0.0f,100.0f),3);
644                _players[_numberOfPlayers].setCatches("Catch/broach.png",catchesPosition, osg::Vec3(0.0f,0.0f,100.0f),10);
645
646                 ++_numberOfPlayers;
647               break;
648            }
649        }               
650    }
651   
652   
653    typedef std::vector< osg::ref_ptr<osgText::Text> > TextList;
654
655    void updateScoreWithCatch()
656    {
657        _currentScore += 1;
658        updateTextWithScore();
659    }
660
661    void updateScoreWithLevel()
662    {
663        osg::Timer_t newTick = osg::Timer::instance()->tick();
664        double timeForLevel = osg::Timer::instance()->delta_s(_levelStartTick, newTick);
665
666        // a ten second level gets you 10 points,
667        // a twenty second levels gets you 5 points.       
668        _currentScore += static_cast<unsigned int>(10000.0f/(timeForLevel*timeForLevel));
669
670        updateTextWithScore();
671
672    }
673
674    void updateTextWithScore()
675    {
676        std::ostringstream os;
677        os<<"Score: "<<_currentScore;
678       
679        std::string textString = os.str();
680   
681        for(TextList::iterator itr = _scoreTextList.begin();
682            itr != _scoreTextList.end();
683            ++itr)
684        {
685            (*itr)->setText(textString);
686        }
687    }       
688   
689    void updateLevelText()
690    {
691        std::ostringstream os;
692        os<<"Level: "<<_level+1;
693        _levelText->setText(os.str());
694    }
695       
696
697protected:
698
699    ~GameEventHandler() {}
700    GameEventHandler(const GameEventHandler&,const osg::CopyOp&) {}
701
702    osg::Vec3 _origin;
703    osg::Vec3 _width;
704    osg::Vec3 _height;
705    osg::Vec3 _originBaseLine;
706    osg::Vec3 _widthBaseLine;
707    float     _characterSize;
708   
709    float _fovy;
710
711    unsigned _level;
712   
713    float _chanceOfExplodingAtStart;
714    float _initialNumDropsPerSecond;
715   
716    osg::ref_ptr<osg::Switch>   _gameSwitch;
717    osg::ref_ptr<osg::Group>    _gameGroup;
718    osg::ref_ptr<osg::Switch>   _levelSwitch;
719   
720    unsigned int                _currentIndex;
721    unsigned int                _welcomeIndex;
722    unsigned int                _lostIndex;
723    unsigned int                _wonIndex;
724    unsigned int                _gameIndex;
725   
726    osg::Timer_t                _levelStartTick;
727    unsigned int                _currentScore;
728   
729    osg::ref_ptr<osgText::Text> _levelText;
730    TextList                    _scoreTextList;
731   
732    unsigned int _numberOfPlayers;
733    Character _players[2];
734
735    typedef std::list< osg::ref_ptr<CatchableObject> > CatchableObjectList;
736    CatchableObjectList _catchableObjects;
737   
738    FileList _backgroundFiles;
739    FileList _benignCatachables;
740
741    bool _leftKeyPressed;
742    bool _rightKeyPressed;
743   
744    osg::ref_ptr<CatchableObject> _dummyCatchable;
745   
746       
747};
748
749
750
751
752GameEventHandler::GameEventHandler()
753{
754    _origin.set(0.0f,0.0f,0.0f);
755    _width.set(1280.0f,0.0f,0.0f);
756    _height.set(0.0f,0.0f,1024.0f);
757    _widthBaseLine = _width*0.9f;
758    _originBaseLine = _origin+_width*0.5-_widthBaseLine*0.5f;
759    _characterSize = _width.length()*0.2f;
760
761    _numberOfPlayers = 0;
762    _level = 0;
763
764    _chanceOfExplodingAtStart = 0.1f;
765    _initialNumDropsPerSecond = 1.0f;
766
767    _leftKeyPressed=false;
768    _rightKeyPressed=false;
769
770    _backgroundFiles.push_back("Catch/sky1.JPG");
771    _backgroundFiles.push_back("Catch/sky3.JPG");
772    _backgroundFiles.push_back("Catch/sky2.JPG");
773    _backgroundFiles.push_back("Catch/farm.JPG");
774
775    _benignCatachables.push_back("Catch/a.png");
776    _benignCatachables.push_back("Catch/b.png");
777    _benignCatachables.push_back("Catch/c.png");
778    _benignCatachables.push_back("Catch/m.png");
779    _benignCatachables.push_back("Catch/n.png");
780    _benignCatachables.push_back("Catch/s.png");
781    _benignCatachables.push_back("Catch/t.png");
782    _benignCatachables.push_back("Catch/u.png");
783    _benignCatachables.push_back("Catch/ball.png");
784   
785    CatchableObject::setUpCatchablesMap(_benignCatachables);
786   
787    _currentScore = 0;
788
789}
790
791bool GameEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
792{
793    if (_currentIndex==_welcomeIndex)
794    {
795        // welcome screen
796        switch(ea.getEventType())
797        {
798            case(osgGA::GUIEventAdapter::KEYDOWN):
799            {
800                _currentIndex = _gameIndex;
801                _gameSwitch->setSingleChildOn(_currentIndex);
802                resetGame();
803                return true;
804            }
805            default:
806                return false;
807        }
808       
809    }
810    else if (_currentIndex==_lostIndex)
811    {
812        // lost screen
813        switch(ea.getEventType())
814        {
815            case(osgGA::GUIEventAdapter::KEYDOWN):
816            {
817                _currentIndex = _gameIndex;
818                _gameSwitch->setSingleChildOn(_currentIndex);
819                resetGame();
820                return true;
821            }
822            default:
823                return false;
824        }
825       
826    }
827    else if (_currentIndex==_wonIndex)
828    {
829        // won screen
830        switch(ea.getEventType())
831        {
832            case(osgGA::GUIEventAdapter::KEYDOWN):
833            {
834                _currentIndex = _gameIndex;
835                _gameSwitch->setSingleChildOn(_currentIndex);
836                resetGame();
837                return true;
838            }
839            default:
840                return false;
841        }
842       
843    }
844    else if (_currentIndex==_gameIndex)
845    {
846        // in game.
847
848        switch(ea.getEventType())
849        {
850            case(osgGA::GUIEventAdapter::FRAME):
851            {
852                // move characters
853                if (_leftKeyPressed)
854                {
855                    if (_numberOfPlayers>=2) _players[1].moveLeft();
856                }
857
858                if (_rightKeyPressed)
859                {
860                    if (_numberOfPlayers>=2) _players[1].moveRight();
861                }
862
863                static double previous_time = ea.getTime();
864                double dt = ea.getTime()-previous_time;
865                previous_time = ea.getTime();
866
867                // move objects
868                for(CatchableObjectList::iterator itr=_catchableObjects.begin();
869                    itr!=_catchableObjects.end();
870                    ++itr)
871                {
872                    (*itr)->update(dt);
873
874                    bool removeEntry = false;
875
876                    for(unsigned int i=0;i<_numberOfPlayers;++i)
877                    {
878                        bool inBasket = ((*itr)->centerInside(_players[i].getCurrentCenterOfBasket(),_players[i].getCurrentRadiusOfBasket()));
879                   
880                        if ((*itr)->dangerous())
881                        {
882                            if ((*itr)->anyInside(_players[i].getLowerLeft(),_players[i].getUpperRight()) || inBasket)
883                            {
884                                // player has hit or caught a dangerous object, must loose a life.
885                                if (!_players[i].looseLife())
886                                {
887                                    _currentIndex = _lostIndex;
888                                    _gameSwitch->setSingleChildOn(_currentIndex);
889
890                                    return true;
891                                }
892                                else
893                                {
894                                    clearCatchables();
895                                    return true;
896                                }
897                            }
898                        }
899                        else if (inBasket)
900                        {
901                            // player has caught a safe object.
902                            updateScoreWithCatch();
903                           
904                            if (!_players[i].addCatch())
905                            {
906                                _players[i].resetCatches();
907                                updateScoreWithLevel();
908                                nextLevel();
909                                if (gameComplete())
910                                {
911                                    _currentIndex = _wonIndex;
912                                    _gameSwitch->setSingleChildOn(_currentIndex);
913                                }
914                                return true;
915                            }
916
917                            removeEntry = true;
918                        }
919                    }
920
921                    if (!(*itr)->anyInside(_origin, _origin+_width+_height) ||
922                        (*itr)->needToRemove(ea.getTime()) ||
923                        removeEntry)
924                    {
925                        // need to remove
926                        // remove child from parents.
927                        osg::ref_ptr<osg::PositionAttitudeTransform> child = (*itr)->_object;
928                        osg::Node::ParentList parents = child->getParents();
929                        for(osg::Node::ParentList::iterator pitr=parents.begin();
930                            pitr!=parents.end();
931                            ++pitr)
932                        {
933                            (*pitr)->removeChild(child.get());
934                        }
935
936                        // remove child from catchable list
937                        itr = _catchableObjects.erase(itr);
938
939                    }
940                    else if ((*itr)->anyInside(_origin, _origin+_width) && !(*itr)->stopped())
941                    {
942                        // hit base line
943                        (*itr)->explode();
944                        (*itr)->stop();
945                        (*itr)->setTimeToRemove(ea.getTime()+3.0);
946                    }
947
948                }
949
950
951                // create new catchable objects
952                static double previousTime = ea.getTime();
953                double deltaTime = ea.getTime()-previousTime;
954                previousTime = ea.getTime();
955
956                float numDropsPerSecond = _initialNumDropsPerSecond * (_level+1);
957                float r = (float)rand()/(float)RAND_MAX;
958                if (r < deltaTime*numDropsPerSecond)
959                {
960                    createNewCatchable();
961                }
962
963
964
965            }
966            case(osgGA::GUIEventAdapter::KEYDOWN):
967            {
968                if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
969                {
970                    _leftKeyPressed=true;
971                    return true;
972                }
973                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
974                {
975                    _rightKeyPressed=true;
976                    return true;
977                }
978            }
979            case(osgGA::GUIEventAdapter::KEYUP):
980            {
981                if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
982                {
983                    _leftKeyPressed=false;
984                    return true;
985                }
986                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
987                {
988                    _rightKeyPressed=false;
989                    return true;
990                }
991            }
992            case(osgGA::GUIEventAdapter::DRAG):
993            case(osgGA::GUIEventAdapter::MOVE):
994            {
995                float px = (ea.getXnormalized()+1.0f)*0.5f;
996
997                if (_numberOfPlayers>=1) _players[0].moveTo(px);
998
999                return true;
1000            }
1001
1002            default:
1003                return false;
1004        }
1005    }
1006    return false;   
1007}
1008
1009void GameEventHandler::getUsage(osg::ApplicationUsage&) const
1010{
1011}
1012
1013osg::Matrix GameEventHandler::getCameraPosition()
1014{
1015    osg::Matrix cameraPosition;
1016    osg::Vec3 center = _origin+(_width+_height)*0.5f;
1017   
1018    float distance = _height.length()/(2.0f*tanf(_fovy*0.5f));
1019   
1020    cameraPosition.makeLookAt(center-osg::Vec3(0.0f,distance,0.0f),center,osg::Vec3(0.0f,0.0f,1.0f));
1021    return cameraPosition;
1022}
1023
1024osg::Node* GameEventHandler::createScene()
1025{
1026    _gameSwitch = new osg::Switch;
1027   
1028    // create a dummy catchable to load all the particule textures to reduce
1029    // latency later on..
1030    _dummyCatchable = new CatchableObject;
1031    _dummyCatchable->setObject("Catch/a.png","a",osg::Vec3(0.0f,0.0,0.0f),1.0f,osg::Vec3(0.0f,0.0,0.0f));
1032    _dummyCatchable->explode();
1033
1034    // set up welcome subgraph
1035    {
1036        osg::Geode* geode = new osg::Geode;
1037
1038        // set up the background
1039        osg::Image* image = osgDB::readImageFile("Catch/Welcome.jpg");
1040        if (image)
1041        {
1042            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1043            osg::StateSet* stateset = geometry->getOrCreateStateSet();
1044            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1045
1046            geode->addDrawable(geometry);
1047        }
1048       
1049        // set up the text
1050        osg::Vec3 textPosition = _origin+_width*0.5f+_height*0.8f -osg::Vec3(0.0f,0.1f,0.0f);
1051        {
1052            osgText::Text* text = new osgText::Text;
1053            text->setText("osgcatch is a childrens catching game\nMove your character using the mouse to\ncatch falling objects in your net\nbut avoid burning objects - they kill!!");
1054            text->setFont("fonts/dirtydoz.ttf");
1055            text->setPosition(textPosition);
1056            text->setCharacterSize(_width.length()*0.025f);
1057            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1058            text->setAlignment(osgText::Text::CENTER_CENTER);
1059            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1060
1061            geode->addDrawable(text);
1062        }
1063       
1064        {
1065            textPosition -= _height*0.25f;
1066            osgText::Text* text = new osgText::Text;
1067            text->setText("Move mouse left and right to move character\nCatch ten objects to advance to next level\nComplete four levels to win.");
1068            text->setFont("fonts/dirtydoz.ttf");
1069            text->setPosition(textPosition);
1070            text->setCharacterSize(_width.length()*0.025f);
1071            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1072            text->setAlignment(osgText::Text::CENTER_CENTER);
1073            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1074
1075            geode->addDrawable(text);
1076        }
1077
1078        {
1079            textPosition -= _height*0.25f;
1080            osgText::Text* text = new osgText::Text;
1081            text->setText("Game concept and artwork - Caitlin Osfield, aged 5!\nSoftware development - Robert Osfield");
1082            text->setFont("fonts/dirtydoz.ttf");
1083            text->setPosition(textPosition);
1084            text->setCharacterSize(_width.length()*0.025f);
1085            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1086            text->setAlignment(osgText::Text::CENTER_CENTER);
1087            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1088
1089            geode->addDrawable(text);
1090        }
1091
1092        {
1093            textPosition -= _height*0.25f;
1094            osgText::Text* text = new osgText::Text;
1095            text->setText("Press any key to start game.\nPress Escape to exit game at any time.");
1096            text->setFont("fonts/dirtydoz.ttf");
1097            text->setPosition(textPosition);
1098            text->setCharacterSize(_width.length()*0.025f);
1099            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1100            text->setAlignment(osgText::Text::CENTER_CENTER);
1101            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1102
1103            geode->addDrawable(text);
1104        }
1105
1106        _welcomeIndex = _gameSwitch->getNumChildren();
1107        _gameSwitch->addChild(geode);
1108    }
1109
1110    // set up you've lost subgraph
1111    {
1112        osg::Geode* geode = new osg::Geode;
1113
1114        osg::Image* image = osgDB::readImageFile("Catch/YouLost.jpg");
1115        if (image)
1116        {
1117            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1118            osg::StateSet* stateset = geometry->getOrCreateStateSet();
1119            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1120
1121            geode->addDrawable(geometry);
1122        }
1123       
1124        // set up the text
1125        osg::Vec3 textPosition = _origin+_width*0.5f+_height*0.75f -osg::Vec3(0.0f,0.1f,0.0f);
1126        {
1127            osgText::Text* text = new osgText::Text;
1128            text->setText("Game Over\nYou lost all three lives");
1129            text->setFont("fonts/dirtydoz.ttf");
1130            text->setPosition(textPosition);
1131            text->setCharacterSize(_width.length()*0.04f);
1132            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1133            text->setAlignment(osgText::Text::CENTER_CENTER);
1134            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1135
1136            geode->addDrawable(text);
1137        }
1138       
1139        {
1140            textPosition -= _height*0.25f;
1141            osgText::Text* text = new osgText::Text;
1142            text->setText("Score: 0");
1143            text->setFont("fonts/dirtydoz.ttf");
1144            text->setPosition(textPosition);
1145            text->setCharacterSize(_width.length()*0.04f);
1146            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1147            text->setAlignment(osgText::Text::CENTER_CENTER);
1148            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1149
1150            geode->addDrawable(text);
1151            _scoreTextList.push_back(text);
1152        }
1153
1154        {
1155            textPosition -= _height*0.25f;
1156            osgText::Text* text = new osgText::Text;
1157            text->setText("Press any key to have another game.\nPress Escape to exit game.");
1158            text->setFont("fonts/dirtydoz.ttf");
1159            text->setPosition(textPosition);
1160            text->setCharacterSize(_width.length()*0.025f);
1161            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1162            text->setAlignment(osgText::Text::CENTER_CENTER);
1163            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1164
1165            geode->addDrawable(text);
1166        }
1167
1168        _lostIndex = _gameSwitch->getNumChildren();
1169        _gameSwitch->addChild(geode);
1170    }
1171
1172    // set up you've won subgraph
1173    {
1174        osg::Geode* geode = new osg::Geode;
1175
1176        osg::Image* image = osgDB::readImageFile("Catch/YouWon.jpg");
1177        if (image)
1178        {
1179            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1180            osg::StateSet* stateset = geometry->getOrCreateStateSet();
1181            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1182
1183            geode->addDrawable(geometry);
1184        }
1185       
1186        // set up the text
1187        osg::Vec3 textPosition = _origin+_width*0.5f+_height*0.75f -osg::Vec3(0.0f,0.1f,0.0f);
1188        {
1189            osgText::Text* text = new osgText::Text;
1190            text->setText("Well done!!!\nYou completed all levels!");
1191            text->setFont("fonts/dirtydoz.ttf");
1192            text->setPosition(textPosition);
1193            text->setCharacterSize(_width.length()*0.04f);
1194            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1195            text->setAlignment(osgText::Text::CENTER_CENTER);
1196            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1197
1198            geode->addDrawable(text);
1199        }
1200       
1201        {
1202            textPosition -= _height*0.25f;
1203            osgText::Text* text = new osgText::Text;
1204            text->setText("Score: 0");
1205            text->setFont("fonts/dirtydoz.ttf");
1206            text->setPosition(textPosition);
1207            text->setCharacterSize(_width.length()*0.04f);
1208            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1209            text->setAlignment(osgText::Text::CENTER_CENTER);
1210            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1211
1212            geode->addDrawable(text);
1213            _scoreTextList.push_back(text);
1214        }
1215
1216        {
1217            textPosition -= _height*0.25f;
1218            osgText::Text* text = new osgText::Text;
1219            text->setText("Press any key to have another game.\nPress Escape to exit game.");
1220            text->setFont("fonts/dirtydoz.ttf");
1221            text->setPosition(textPosition);
1222            text->setCharacterSize(_width.length()*0.025f);
1223            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1224            text->setAlignment(osgText::Text::CENTER_CENTER);
1225            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1226
1227            geode->addDrawable(text);
1228        }
1229
1230        _wonIndex = _gameSwitch->getNumChildren();
1231        _gameSwitch->addChild(geode);
1232    }
1233
1234    // set up game subgraph.
1235    {
1236        _gameGroup = new osg::Group;
1237
1238        if (_numberOfPlayers==0)
1239        {
1240            addPlayer(PLAYER_GIRL);
1241        }
1242
1243        for(unsigned int i=0;i<_numberOfPlayers;++i)
1244        {
1245            _gameGroup->addChild(_players[i]._character.get());
1246            _gameGroup->addChild(_players[i]._livesSwitch.get());
1247            _gameGroup->addChild(_players[i]._catchSwitch.get());
1248        }   
1249
1250        // background
1251        {
1252            _levelSwitch = new osg::Switch;
1253
1254            for(FileList::const_iterator itr = _backgroundFiles.begin();
1255                itr != _backgroundFiles.end();
1256                ++itr)
1257            {
1258
1259                osg::Image* image = osgDB::readImageFile(*itr);
1260                if (image)
1261                {
1262                    osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1263                    osg::StateSet* stateset = geometry->getOrCreateStateSet();
1264                    stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1265
1266                    osg::Geode* geode = new osg::Geode;
1267                    geode->addDrawable(geometry);
1268
1269                    _levelSwitch->addChild(geode);
1270                }
1271            }
1272            _levelSwitch->setSingleChildOn(0);
1273            _gameGroup->addChild(_levelSwitch.get());
1274        }
1275
1276
1277        _gameIndex = _gameSwitch->getNumChildren();
1278        _gameSwitch->addChild(_gameGroup.get());
1279
1280        // set up the text
1281        osg::Vec3 textPosition = _origin+_width*0.05f+_height*0.95f-osg::Vec3(0.0f,0.1f,0.0f);
1282        {
1283            osgText::Text* text = new osgText::Text;
1284            text->setText("Score : 0");
1285            text->setFont("fonts/dirtydoz.ttf");
1286            text->setPosition(textPosition);
1287            text->setCharacterSize(_width.length()*0.04f);
1288            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1289            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1290
1291            osg::Geode* geode = new osg::Geode;
1292            geode->addDrawable(text);
1293            _scoreTextList.push_back(text);
1294           
1295            textPosition -= _height*0.05f;
1296            _levelText = new osgText::Text;
1297            _levelText->setText("Level : 0");
1298            _levelText->setFont("fonts/dirtydoz.ttf");
1299            _levelText->setPosition(textPosition);
1300            _levelText->setCharacterSize(_width.length()*0.04f);
1301            _levelText->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1302            _levelText->setAxisAlignment(osgText::Text::XZ_PLANE);
1303
1304            geode->addDrawable(_levelText.get());
1305           
1306
1307
1308            _gameGroup->addChild(geode);
1309        }
1310
1311
1312    }
1313   
1314    _currentIndex = _welcomeIndex;
1315    _gameSwitch->setSingleChildOn(_currentIndex);
1316
1317    return _gameSwitch.get();
1318}
1319
1320void GameEventHandler::createNewCatchable()
1321{
1322    if (_benignCatachables.empty()) return;
1323
1324    unsigned int catachableIndex = (unsigned int)((float)_benignCatachables.size()*(float)rand()/(float)RAND_MAX);
1325    if (catachableIndex>=_benignCatachables.size()) catachableIndex = _benignCatachables.size()-1;
1326   
1327    const std::string& filename = _benignCatachables[catachableIndex];
1328
1329    float ratio = ((float)rand() / (float)RAND_MAX);
1330    float size = 20.0f+100.0f*((float)rand() / (float)RAND_MAX);
1331    float angle = osg::PI*0.25f + 0.5f*osg::PI*((float)rand() / (float)RAND_MAX);
1332    float speed = 200.0f*((float)rand() / (float)RAND_MAX);
1333
1334    CatchableObject* catchableObject = new CatchableObject;
1335    osg::Vec3 position = _origin+_height+_width*ratio + osg::Vec3(0.0f,-0.7f,0.0f);
1336    osg::Vec3 velocity(-cosf(angle)*speed,0.0f,-sinf(angle)*speed);
1337    //std::cout<<"angle = "<<angle<<" velocity="<<velocity<<std::endl;
1338    catchableObject->setObject(filename,"boy",position,size,velocity);
1339    _catchableObjects.push_back(catchableObject);
1340
1341    float r = (float)rand() / (float)RAND_MAX;
1342    if (r < _chanceOfExplodingAtStart)
1343    {
1344       catchableObject->explode();
1345    }
1346
1347    _gameGroup->addChild(catchableObject->_object.get());
1348}
1349
1350
1351class CompileStateCallback : public osgProducer::OsgCameraGroup::RealizeCallback
1352{
1353    public:
1354        CompileStateCallback(GameEventHandler* eh):_gameEventHandler(eh) {}
1355       
1356        virtual void operator()( osgProducer::OsgCameraGroup&, osgProducer::OsgSceneHandler& sh, const Producer::RenderSurface& )
1357        {
1358            // now safe to construct
1359            sh.init();
1360         
1361            {
1362                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
1363
1364                if (_gameEventHandler)
1365                {
1366                    _gameEventHandler->compileGLObjects(*(sh.getSceneView()->getState()));
1367                }
1368            }
1369        }
1370       
1371       
1372        OpenThreads::Mutex  _mutex;
1373        GameEventHandler*  _gameEventHandler;
1374       
1375};
1376
1377int main( int argc, char **argv )
1378{
1379
1380    // use an ArgumentParser object to manage the program arguments.
1381    osg::ArgumentParser arguments(&argc,argv);
1382   
1383    // set up the usage document, in case we need to print out how to use this program.
1384    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
1385    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye");
1386    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in sceonds between the display of successive image pairs when in auto advance mode.");
1387    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
1388    arguments.getApplicationUsage()->addCommandLineOption("-x <float>","Horizontal offset of left and right images.");
1389    arguments.getApplicationUsage()->addCommandLineOption("-y <float>","Vertical offset of left and right images.");
1390    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
1391   
1392
1393    // construct the viewer.
1394    osgProducer::Viewer viewer(arguments);
1395
1396    // set up the value with sensible default event handlers.
1397    viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE);
1398
1399    // register the handler to add keyboard and mosue handling.
1400    GameEventHandler* seh = new GameEventHandler();
1401    viewer.getEventHandlerList().push_front(seh);
1402
1403    while (arguments.read("--boy")) seh->addPlayer(GameEventHandler::PLAYER_BOY);
1404    while (arguments.read("--girl")) seh->addPlayer(GameEventHandler::PLAYER_GIRL);
1405   
1406   
1407
1408    // get details on keyboard and mouse bindings used by the viewer.
1409    viewer.getUsage(*arguments.getApplicationUsage());
1410
1411    // if user request help write it out to cout.
1412    if (arguments.read("-h") || arguments.read("--help"))
1413    {
1414        arguments.getApplicationUsage()->write(std::cout);
1415        return 1;
1416    }
1417
1418    // any option left unread are converted into errors to write out later.
1419    arguments.reportRemainingOptionsAsUnrecognized();
1420
1421    // report any errors if they have occured when parsing the program aguments.
1422    if (arguments.errors())
1423    {
1424        arguments.writeErrorMessages(std::cout);
1425        return 1;
1426    }
1427   
1428    // now the windows have been realized we switch off the cursor to prevent it
1429    // distracting the people seeing the stereo images.
1430    float fovy = 1.0f;
1431    for( unsigned int i = 0; i < viewer.getNumberOfCameras(); i++ )
1432    {
1433        Producer::Camera* cam = viewer.getCamera(i);
1434        Producer::RenderSurface* rs = cam->getRenderSurface();
1435        rs->useCursor(false);
1436        fovy = osg::DegreesToRadians(cam->getLensVerticalFov());
1437    }
1438   
1439    seh->setFOVY(fovy);
1440   
1441    // enable the image cache so we don't need to keep loading the particle files
1442    osgDB::ReaderWriter::Options* options = new osgDB::ReaderWriter::Options;
1443    options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_IMAGES);
1444    osgDB::Registry::instance()->setOptions(options);
1445
1446
1447    // creat the scene from the file list.
1448    osg::ref_ptr<osg::Node> rootNode = seh->createScene();
1449
1450    //osgDB::writeNodeFile(*rootNode,"test.osg");
1451
1452    // set the scene to render
1453    viewer.setSceneData(rootNode.get());
1454
1455    viewer.setRealizeCallback(new CompileStateCallback(seh));
1456
1457    // create the windows and run the threads, note has to be single threaded
1458    // due to use osgParticle
1459    viewer.realize(Producer::CameraGroup::SingleThreaded);
1460   
1461    viewer.requestWarpPointer(0.5f,0.5f);
1462       
1463
1464    while( !viewer.done() )
1465    {
1466        // wait for all cull and draw threads to complete.
1467        viewer.sync();
1468
1469        // update the scene by traversing it with the the update visitor which will
1470        // call all node update callbacks and animations.
1471        viewer.update();
1472         
1473        viewer.setView(seh->getCameraPosition());
1474
1475        // fire off the cull and draw traversals of the scene.
1476        viewer.frame();
1477       
1478    }
1479
1480    // wait for all cull and draw threads to complete.
1481    viewer.sync();
1482
1483    // run a clean up frame to delete all OpenGL objects.
1484    viewer.cleanup_frame();
1485
1486    // wait for all the clean up frame to complete.
1487    viewer.sync();
1488   
1489    return 0;
1490}
Note: See TracBrowser for help on using the browser.