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

Revision 5064, 47.9 kB (checked in by robert, 8 years ago)

Build fixes to cope with changes to Producer/osgProducer.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgProducer/Viewer>
15#include <osgDB/ReadFile>
16#include <osgDB/WriteFile>
17
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 void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }
510
511    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
512   
513    virtual void getUsage(osg::ApplicationUsage& usage) const;
514   
515    osg::Matrix getCameraPosition();
516   
517    void compileGLObjects(osg::State& state)
518    {
519        osgUtil::GLObjectsVisitor compile;
520        compile.setState(&state);
521   
522        for(ObjectMap::iterator itr = s_objectMap.begin();
523            itr != s_objectMap.end();
524            ++itr)
525        {
526            itr->second->accept(compile);
527        }
528    }
529   
530    osg::Node* createScene();
531   
532    void setFOVY(float fovy) { _fovy = fovy; }
533    float getFOVY() const { return _fovy; }
534   
535    void createNewCatchable();
536   
537    void clearCatchables()
538    {
539        for(CatchableObjectList::iterator itr=_catchableObjects.begin();
540            itr!=_catchableObjects.end();
541            ++itr)
542        {
543            // need to remove
544            // remove child from parents.
545            osg::ref_ptr<osg::PositionAttitudeTransform> child = (*itr)->_object;
546            osg::Node::ParentList parents = child->getParents();
547            for(osg::Node::ParentList::iterator pitr=parents.begin();
548                pitr!=parents.end();
549                ++pitr)
550            {
551                (*pitr)->removeChild(child.get());
552            }
553        }
554
555        _catchableObjects.clear();
556    }
557   
558    void resetLevel()
559    {
560        _level = 0;
561        _levelSwitch->setSingleChildOn(_level);
562        clearCatchables();
563
564        updateLevelText();
565
566        _levelStartTick = osg::Timer::instance()->tick();
567    }
568   
569    void nextLevel()
570    {
571        ++_level;
572        if (_level < _levelSwitch->getNumChildren())
573        {
574            _levelSwitch->setSingleChildOn(_level);
575            clearCatchables();
576        }
577
578        updateLevelText();
579
580        _levelStartTick = osg::Timer::instance()->tick();
581    }
582
583    bool gameComplete()
584    {
585        return _level >= _levelSwitch->getNumChildren();
586    }
587
588    void resetGame()
589    {
590        _currentScore = 0;
591       
592        updateTextWithScore();
593
594        clearCatchables();
595        resetLevel();
596       
597        for(unsigned int i=0;i<_numberOfPlayers;++i)
598        {
599            _players[i].reset();
600        }
601    }
602
603
604    enum Players
605    {
606        PLAYER_GIRL,
607        PLAYER_BOY
608    };
609
610    void addPlayer(Players player)
611    {
612        osg::Vec3 livesPosition;
613        osg::Vec3 catchesPosition;
614        if (_numberOfPlayers==0)
615        {
616            livesPosition = _originBaseLine+osg::Vec3(0.0f,-0.5f,0.0f);
617            catchesPosition = _originBaseLine+osg::Vec3(100.0f,-0.5f,0.0f);
618        }
619        else
620        {
621            livesPosition = _originBaseLine+osg::Vec3(1000.0f,-0.5f,000.0f);
622            catchesPosition = _originBaseLine+osg::Vec3(1100.0f,-0.5f,0.0f);
623        }
624       
625        switch(player)
626        {
627            case PLAYER_GIRL:
628            {
629                std::string player_one = "Catch/girl.png";
630                osg::Vec3 catchPos(0.2, 0.57, 0.34);
631
632                _players[_numberOfPlayers].setCharacter(player_one,"girl", _originBaseLine + osg::Vec3(0.0f,-1.0f,0.0f), _widthBaseLine, catchPos, 0.5f);
633                _players[_numberOfPlayers].setLives(player_one,livesPosition, osg::Vec3(0.0f,0.0f,100.0f),3);
634                _players[_numberOfPlayers].setCatches("Catch/broach.png",catchesPosition, osg::Vec3(0.0f,0.0f,100.0f),10);
635
636                ++_numberOfPlayers;
637                break;
638            }
639            case PLAYER_BOY:
640            {
641                std::string player_two = "Catch/boy.png";
642                osg::Vec3 catchPos(0.8, 0.57, 0.34);
643
644                _players[_numberOfPlayers].setCharacter(player_two,"boy", _originBaseLine + osg::Vec3(0.0f,-2.0f,0.0f), _widthBaseLine, catchPos, 0.5f);
645                _players[_numberOfPlayers].setLives(player_two,livesPosition, osg::Vec3(0.0f,0.0f,100.0f),3);
646                _players[_numberOfPlayers].setCatches("Catch/broach.png",catchesPosition, osg::Vec3(0.0f,0.0f,100.0f),10);
647
648                 ++_numberOfPlayers;
649               break;
650            }
651        }               
652    }
653   
654   
655    typedef std::vector< osg::ref_ptr<osgText::Text> > TextList;
656
657    void updateScoreWithCatch()
658    {
659        _currentScore += 1;
660        updateTextWithScore();
661    }
662
663    void updateScoreWithLevel()
664    {
665        osg::Timer_t newTick = osg::Timer::instance()->tick();
666        double timeForLevel = osg::Timer::instance()->delta_s(_levelStartTick, newTick);
667
668        // a ten second level gets you 10 points,
669        // a twenty second levels gets you 5 points.       
670        _currentScore += static_cast<unsigned int>(10000.0f/(timeForLevel*timeForLevel));
671
672        updateTextWithScore();
673
674    }
675
676    void updateTextWithScore()
677    {
678        std::ostringstream os;
679        os<<"Score: "<<_currentScore;
680       
681        std::string textString = os.str();
682   
683        for(TextList::iterator itr = _scoreTextList.begin();
684            itr != _scoreTextList.end();
685            ++itr)
686        {
687            (*itr)->setText(textString);
688        }
689    }       
690   
691    void updateLevelText()
692    {
693        std::ostringstream os;
694        os<<"Level: "<<_level+1;
695        _levelText->setText(os.str());
696    }
697       
698
699protected:
700
701    ~GameEventHandler() {}
702    GameEventHandler(const GameEventHandler&,const osg::CopyOp&) {}
703
704    osg::Vec3 _origin;
705    osg::Vec3 _width;
706    osg::Vec3 _height;
707    osg::Vec3 _originBaseLine;
708    osg::Vec3 _widthBaseLine;
709    float     _characterSize;
710   
711    float _fovy;
712
713    unsigned _level;
714   
715    float _chanceOfExplodingAtStart;
716    float _initialNumDropsPerSecond;
717   
718    osg::ref_ptr<osg::Switch>   _gameSwitch;
719    osg::ref_ptr<osg::Group>    _gameGroup;
720    osg::ref_ptr<osg::Switch>   _levelSwitch;
721   
722    unsigned int                _currentIndex;
723    unsigned int                _welcomeIndex;
724    unsigned int                _lostIndex;
725    unsigned int                _wonIndex;
726    unsigned int                _gameIndex;
727   
728    osg::Timer_t                _levelStartTick;
729    unsigned int                _currentScore;
730   
731    osg::ref_ptr<osgText::Text> _levelText;
732    TextList                    _scoreTextList;
733   
734    unsigned int _numberOfPlayers;
735    Character _players[2];
736
737    typedef std::list< osg::ref_ptr<CatchableObject> > CatchableObjectList;
738    CatchableObjectList _catchableObjects;
739   
740    FileList _backgroundFiles;
741    FileList _benignCatachables;
742
743    bool _leftKeyPressed;
744    bool _rightKeyPressed;
745   
746    osg::ref_ptr<CatchableObject> _dummyCatchable;
747   
748       
749};
750
751
752
753
754GameEventHandler::GameEventHandler()
755{
756    _origin.set(0.0f,0.0f,0.0f);
757    _width.set(1280.0f,0.0f,0.0f);
758    _height.set(0.0f,0.0f,1024.0f);
759    _widthBaseLine = _width*0.9f;
760    _originBaseLine = _origin+_width*0.5-_widthBaseLine*0.5f;
761    _characterSize = _width.length()*0.2f;
762
763    _numberOfPlayers = 0;
764    _level = 0;
765
766    _chanceOfExplodingAtStart = 0.1f;
767    _initialNumDropsPerSecond = 1.0f;
768
769    _leftKeyPressed=false;
770    _rightKeyPressed=false;
771
772    _backgroundFiles.push_back("Catch/sky1.JPG");
773    _backgroundFiles.push_back("Catch/sky3.JPG");
774    _backgroundFiles.push_back("Catch/sky2.JPG");
775    _backgroundFiles.push_back("Catch/farm.JPG");
776
777    _benignCatachables.push_back("Catch/a.png");
778    _benignCatachables.push_back("Catch/b.png");
779    _benignCatachables.push_back("Catch/c.png");
780    _benignCatachables.push_back("Catch/m.png");
781    _benignCatachables.push_back("Catch/n.png");
782    _benignCatachables.push_back("Catch/s.png");
783    _benignCatachables.push_back("Catch/t.png");
784    _benignCatachables.push_back("Catch/u.png");
785    _benignCatachables.push_back("Catch/ball.png");
786   
787    CatchableObject::setUpCatchablesMap(_benignCatachables);
788   
789    _currentScore = 0;
790
791}
792
793bool GameEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
794{
795    if (_currentIndex==_welcomeIndex)
796    {
797        // welcome screen
798        switch(ea.getEventType())
799        {
800            case(osgGA::GUIEventAdapter::KEYDOWN):
801            {
802                _currentIndex = _gameIndex;
803                _gameSwitch->setSingleChildOn(_currentIndex);
804                resetGame();
805                return true;
806            }
807            default:
808                return false;
809        }
810       
811    }
812    else if (_currentIndex==_lostIndex)
813    {
814        // lost screen
815        switch(ea.getEventType())
816        {
817            case(osgGA::GUIEventAdapter::KEYDOWN):
818            {
819                _currentIndex = _gameIndex;
820                _gameSwitch->setSingleChildOn(_currentIndex);
821                resetGame();
822                return true;
823            }
824            default:
825                return false;
826        }
827       
828    }
829    else if (_currentIndex==_wonIndex)
830    {
831        // won screen
832        switch(ea.getEventType())
833        {
834            case(osgGA::GUIEventAdapter::KEYDOWN):
835            {
836                _currentIndex = _gameIndex;
837                _gameSwitch->setSingleChildOn(_currentIndex);
838                resetGame();
839                return true;
840            }
841            default:
842                return false;
843        }
844       
845    }
846    else if (_currentIndex==_gameIndex)
847    {
848        // in game.
849
850        switch(ea.getEventType())
851        {
852            case(osgGA::GUIEventAdapter::FRAME):
853            {
854                // move characters
855                if (_leftKeyPressed)
856                {
857                    if (_numberOfPlayers>=2) _players[1].moveLeft();
858                }
859
860                if (_rightKeyPressed)
861                {
862                    if (_numberOfPlayers>=2) _players[1].moveRight();
863                }
864
865                static double previous_time = ea.getTime();
866                double dt = ea.getTime()-previous_time;
867                previous_time = ea.getTime();
868
869                // move objects
870                for(CatchableObjectList::iterator itr=_catchableObjects.begin();
871                    itr!=_catchableObjects.end();
872                    ++itr)
873                {
874                    (*itr)->update(dt);
875
876                    bool removeEntry = false;
877
878                    for(unsigned int i=0;i<_numberOfPlayers;++i)
879                    {
880                        bool inBasket = ((*itr)->centerInside(_players[i].getCurrentCenterOfBasket(),_players[i].getCurrentRadiusOfBasket()));
881                   
882                        if ((*itr)->dangerous())
883                        {
884                            if ((*itr)->anyInside(_players[i].getLowerLeft(),_players[i].getUpperRight()) || inBasket)
885                            {
886                                // player has hit or caught a dangerous object, must loose a life.
887                                if (!_players[i].looseLife())
888                                {
889                                    _currentIndex = _lostIndex;
890                                    _gameSwitch->setSingleChildOn(_currentIndex);
891
892                                    return true;
893                                }
894                                else
895                                {
896                                    clearCatchables();
897                                    return true;
898                                }
899                            }
900                        }
901                        else if (inBasket)
902                        {
903                            // player has caught a safe object.
904                            updateScoreWithCatch();
905                           
906                            if (!_players[i].addCatch())
907                            {
908                                _players[i].resetCatches();
909                                updateScoreWithLevel();
910                                nextLevel();
911                                if (gameComplete())
912                                {
913                                    _currentIndex = _wonIndex;
914                                    _gameSwitch->setSingleChildOn(_currentIndex);
915                                }
916                                return true;
917                            }
918
919                            removeEntry = true;
920                        }
921                    }
922
923                    if (!(*itr)->anyInside(_origin, _origin+_width+_height) ||
924                        (*itr)->needToRemove(ea.getTime()) ||
925                        removeEntry)
926                    {
927                        // need to remove
928                        // remove child from parents.
929                        osg::ref_ptr<osg::PositionAttitudeTransform> child = (*itr)->_object;
930                        osg::Node::ParentList parents = child->getParents();
931                        for(osg::Node::ParentList::iterator pitr=parents.begin();
932                            pitr!=parents.end();
933                            ++pitr)
934                        {
935                            (*pitr)->removeChild(child.get());
936                        }
937
938                        // remove child from catchable list
939                        itr = _catchableObjects.erase(itr);
940
941                    }
942                    else if ((*itr)->anyInside(_origin, _origin+_width) && !(*itr)->stopped())
943                    {
944                        // hit base line
945                        (*itr)->explode();
946                        (*itr)->stop();
947                        (*itr)->setTimeToRemove(ea.getTime()+3.0);
948                    }
949
950                }
951
952
953                // create new catchable objects
954                static double previousTime = ea.getTime();
955                double deltaTime = ea.getTime()-previousTime;
956                previousTime = ea.getTime();
957
958                float numDropsPerSecond = _initialNumDropsPerSecond * (_level+1);
959                float r = (float)rand()/(float)RAND_MAX;
960                if (r < deltaTime*numDropsPerSecond)
961                {
962                    createNewCatchable();
963                }
964
965
966
967            }
968            case(osgGA::GUIEventAdapter::KEYDOWN):
969            {
970                if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
971                {
972                    _leftKeyPressed=true;
973                    return true;
974                }
975                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
976                {
977                    _rightKeyPressed=true;
978                    return true;
979                }
980            }
981            case(osgGA::GUIEventAdapter::KEYUP):
982            {
983                if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
984                {
985                    _leftKeyPressed=false;
986                    return true;
987                }
988                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
989                {
990                    _rightKeyPressed=false;
991                    return true;
992                }
993            }
994            case(osgGA::GUIEventAdapter::DRAG):
995            case(osgGA::GUIEventAdapter::MOVE):
996            {
997                float px = (ea.getXnormalized()+1.0f)*0.5f;
998
999                if (_numberOfPlayers>=1) _players[0].moveTo(px);
1000
1001                return true;
1002            }
1003
1004            default:
1005                return false;
1006        }
1007    }
1008    return false;   
1009}
1010
1011void GameEventHandler::getUsage(osg::ApplicationUsage&) const
1012{
1013}
1014
1015osg::Matrix GameEventHandler::getCameraPosition()
1016{
1017    osg::Matrix cameraPosition;
1018    osg::Vec3 center = _origin+(_width+_height)*0.5f;
1019   
1020    float distance = _height.length()/(2.0f*tanf(_fovy*0.5f));
1021   
1022    cameraPosition.makeLookAt(center-osg::Vec3(0.0f,distance,0.0f),center,osg::Vec3(0.0f,0.0f,1.0f));
1023    return cameraPosition;
1024}
1025
1026osg::Node* GameEventHandler::createScene()
1027{
1028    _gameSwitch = new osg::Switch;
1029   
1030    // create a dummy catchable to load all the particule textures to reduce
1031    // latency later on..
1032    _dummyCatchable = new CatchableObject;
1033    _dummyCatchable->setObject("Catch/a.png","a",osg::Vec3(0.0f,0.0,0.0f),1.0f,osg::Vec3(0.0f,0.0,0.0f));
1034    _dummyCatchable->explode();
1035
1036    // set up welcome subgraph
1037    {
1038        osg::Geode* geode = new osg::Geode;
1039
1040        // set up the background
1041        osg::Image* image = osgDB::readImageFile("Catch/Welcome.jpg");
1042        if (image)
1043        {
1044            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1045            osg::StateSet* stateset = geometry->getOrCreateStateSet();
1046            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1047
1048            geode->addDrawable(geometry);
1049        }
1050       
1051        // set up the text
1052        osg::Vec3 textPosition = _origin+_width*0.5f+_height*0.8f -osg::Vec3(0.0f,0.1f,0.0f);
1053        {
1054            osgText::Text* text = new osgText::Text;
1055            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!!");
1056            text->setFont("fonts/dirtydoz.ttf");
1057            text->setPosition(textPosition);
1058            text->setCharacterSize(_width.length()*0.025f);
1059            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1060            text->setAlignment(osgText::Text::CENTER_CENTER);
1061            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1062
1063            geode->addDrawable(text);
1064        }
1065       
1066        {
1067            textPosition -= _height*0.25f;
1068            osgText::Text* text = new osgText::Text;
1069            text->setText("Move mouse left and right to move character\nCatch ten objects to advance to next level\nComplete four levels to win.");
1070            text->setFont("fonts/dirtydoz.ttf");
1071            text->setPosition(textPosition);
1072            text->setCharacterSize(_width.length()*0.025f);
1073            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1074            text->setAlignment(osgText::Text::CENTER_CENTER);
1075            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1076
1077            geode->addDrawable(text);
1078        }
1079
1080        {
1081            textPosition -= _height*0.25f;
1082            osgText::Text* text = new osgText::Text;
1083            text->setText("Game concept and artwork - Caitlin Osfield, aged 5!\nSoftware development - Robert Osfield");
1084            text->setFont("fonts/dirtydoz.ttf");
1085            text->setPosition(textPosition);
1086            text->setCharacterSize(_width.length()*0.025f);
1087            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1088            text->setAlignment(osgText::Text::CENTER_CENTER);
1089            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1090
1091            geode->addDrawable(text);
1092        }
1093
1094        {
1095            textPosition -= _height*0.25f;
1096            osgText::Text* text = new osgText::Text;
1097            text->setText("Press any key to start game.\nPress Escape to exit game at any time.");
1098            text->setFont("fonts/dirtydoz.ttf");
1099            text->setPosition(textPosition);
1100            text->setCharacterSize(_width.length()*0.025f);
1101            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1102            text->setAlignment(osgText::Text::CENTER_CENTER);
1103            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1104
1105            geode->addDrawable(text);
1106        }
1107
1108        _welcomeIndex = _gameSwitch->getNumChildren();
1109        _gameSwitch->addChild(geode);
1110    }
1111
1112    // set up you've lost subgraph
1113    {
1114        osg::Geode* geode = new osg::Geode;
1115
1116        osg::Image* image = osgDB::readImageFile("Catch/YouLost.jpg");
1117        if (image)
1118        {
1119            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1120            osg::StateSet* stateset = geometry->getOrCreateStateSet();
1121            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1122
1123            geode->addDrawable(geometry);
1124        }
1125       
1126        // set up the text
1127        osg::Vec3 textPosition = _origin+_width*0.5f+_height*0.75f -osg::Vec3(0.0f,0.1f,0.0f);
1128        {
1129            osgText::Text* text = new osgText::Text;
1130            text->setText("Game Over\nYou lost all three lives");
1131            text->setFont("fonts/dirtydoz.ttf");
1132            text->setPosition(textPosition);
1133            text->setCharacterSize(_width.length()*0.04f);
1134            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1135            text->setAlignment(osgText::Text::CENTER_CENTER);
1136            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1137
1138            geode->addDrawable(text);
1139        }
1140       
1141        {
1142            textPosition -= _height*0.25f;
1143            osgText::Text* text = new osgText::Text;
1144            text->setText("Score: 0");
1145            text->setFont("fonts/dirtydoz.ttf");
1146            text->setPosition(textPosition);
1147            text->setCharacterSize(_width.length()*0.04f);
1148            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1149            text->setAlignment(osgText::Text::CENTER_CENTER);
1150            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1151
1152            geode->addDrawable(text);
1153            _scoreTextList.push_back(text);
1154        }
1155
1156        {
1157            textPosition -= _height*0.25f;
1158            osgText::Text* text = new osgText::Text;
1159            text->setText("Press any key to have another game.\nPress Escape to exit game.");
1160            text->setFont("fonts/dirtydoz.ttf");
1161            text->setPosition(textPosition);
1162            text->setCharacterSize(_width.length()*0.025f);
1163            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1164            text->setAlignment(osgText::Text::CENTER_CENTER);
1165            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1166
1167            geode->addDrawable(text);
1168        }
1169
1170        _lostIndex = _gameSwitch->getNumChildren();
1171        _gameSwitch->addChild(geode);
1172    }
1173
1174    // set up you've won subgraph
1175    {
1176        osg::Geode* geode = new osg::Geode;
1177
1178        osg::Image* image = osgDB::readImageFile("Catch/YouWon.jpg");
1179        if (image)
1180        {
1181            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1182            osg::StateSet* stateset = geometry->getOrCreateStateSet();
1183            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1184
1185            geode->addDrawable(geometry);
1186        }
1187       
1188        // set up the text
1189        osg::Vec3 textPosition = _origin+_width*0.5f+_height*0.75f -osg::Vec3(0.0f,0.1f,0.0f);
1190        {
1191            osgText::Text* text = new osgText::Text;
1192            text->setText("Well done!!!\nYou completed all levels!");
1193            text->setFont("fonts/dirtydoz.ttf");
1194            text->setPosition(textPosition);
1195            text->setCharacterSize(_width.length()*0.04f);
1196            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1197            text->setAlignment(osgText::Text::CENTER_CENTER);
1198            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1199
1200            geode->addDrawable(text);
1201        }
1202       
1203        {
1204            textPosition -= _height*0.25f;
1205            osgText::Text* text = new osgText::Text;
1206            text->setText("Score: 0");
1207            text->setFont("fonts/dirtydoz.ttf");
1208            text->setPosition(textPosition);
1209            text->setCharacterSize(_width.length()*0.04f);
1210            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1211            text->setAlignment(osgText::Text::CENTER_CENTER);
1212            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1213
1214            geode->addDrawable(text);
1215            _scoreTextList.push_back(text);
1216        }
1217
1218        {
1219            textPosition -= _height*0.25f;
1220            osgText::Text* text = new osgText::Text;
1221            text->setText("Press any key to have another game.\nPress Escape to exit game.");
1222            text->setFont("fonts/dirtydoz.ttf");
1223            text->setPosition(textPosition);
1224            text->setCharacterSize(_width.length()*0.025f);
1225            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1226            text->setAlignment(osgText::Text::CENTER_CENTER);
1227            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1228
1229            geode->addDrawable(text);
1230        }
1231
1232        _wonIndex = _gameSwitch->getNumChildren();
1233        _gameSwitch->addChild(geode);
1234    }
1235
1236    // set up game subgraph.
1237    {
1238        _gameGroup = new osg::Group;
1239
1240        if (_numberOfPlayers==0)
1241        {
1242            addPlayer(PLAYER_GIRL);
1243        }
1244
1245        for(unsigned int i=0;i<_numberOfPlayers;++i)
1246        {
1247            _gameGroup->addChild(_players[i]._character.get());
1248            _gameGroup->addChild(_players[i]._livesSwitch.get());
1249            _gameGroup->addChild(_players[i]._catchSwitch.get());
1250        }   
1251
1252        // background
1253        {
1254            _levelSwitch = new osg::Switch;
1255
1256            for(FileList::const_iterator itr = _backgroundFiles.begin();
1257                itr != _backgroundFiles.end();
1258                ++itr)
1259            {
1260
1261                osg::Image* image = osgDB::readImageFile(*itr);
1262                if (image)
1263                {
1264                    osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
1265                    osg::StateSet* stateset = geometry->getOrCreateStateSet();
1266                    stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
1267
1268                    osg::Geode* geode = new osg::Geode;
1269                    geode->addDrawable(geometry);
1270
1271                    _levelSwitch->addChild(geode);
1272                }
1273            }
1274            _levelSwitch->setSingleChildOn(0);
1275            _gameGroup->addChild(_levelSwitch.get());
1276        }
1277
1278
1279        _gameIndex = _gameSwitch->getNumChildren();
1280        _gameSwitch->addChild(_gameGroup.get());
1281
1282        // set up the text
1283        osg::Vec3 textPosition = _origin+_width*0.05f+_height*0.95f-osg::Vec3(0.0f,0.1f,0.0f);
1284        {
1285            osgText::Text* text = new osgText::Text;
1286            text->setText("Score : 0");
1287            text->setFont("fonts/dirtydoz.ttf");
1288            text->setPosition(textPosition);
1289            text->setCharacterSize(_width.length()*0.04f);
1290            text->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1291            text->setAxisAlignment(osgText::Text::XZ_PLANE);
1292
1293            osg::Geode* geode = new osg::Geode;
1294            geode->addDrawable(text);
1295            _scoreTextList.push_back(text);
1296           
1297            textPosition -= _height*0.05f;
1298            _levelText = new osgText::Text;
1299            _levelText->setText("Level : 0");
1300            _levelText->setFont("fonts/dirtydoz.ttf");
1301            _levelText->setPosition(textPosition);
1302            _levelText->setCharacterSize(_width.length()*0.04f);
1303            _levelText->setColor(osg::Vec4(0.0f,0.2f,0.2f,1.0f));
1304            _levelText->setAxisAlignment(osgText::Text::XZ_PLANE);
1305
1306            geode->addDrawable(_levelText.get());
1307           
1308
1309
1310            _gameGroup->addChild(geode);
1311        }
1312
1313
1314    }
1315   
1316    _currentIndex = _welcomeIndex;
1317    _gameSwitch->setSingleChildOn(_currentIndex);
1318
1319    return _gameSwitch.get();
1320}
1321
1322void GameEventHandler::createNewCatchable()
1323{
1324    if (_benignCatachables.empty()) return;
1325
1326    unsigned int catachableIndex = (unsigned int)((float)_benignCatachables.size()*(float)rand()/(float)RAND_MAX);
1327    if (catachableIndex>=_benignCatachables.size()) catachableIndex = _benignCatachables.size()-1;
1328   
1329    const std::string& filename = _benignCatachables[catachableIndex];
1330
1331    float ratio = ((float)rand() / (float)RAND_MAX);
1332    float size = 20.0f+100.0f*((float)rand() / (float)RAND_MAX);
1333    float angle = osg::PI*0.25f + 0.5f*osg::PI*((float)rand() / (float)RAND_MAX);
1334    float speed = 200.0f*((float)rand() / (float)RAND_MAX);
1335
1336    CatchableObject* catchableObject = new CatchableObject;
1337    osg::Vec3 position = _origin+_height+_width*ratio + osg::Vec3(0.0f,-0.7f,0.0f);
1338    osg::Vec3 velocity(-cosf(angle)*speed,0.0f,-sinf(angle)*speed);
1339    //std::cout<<"angle = "<<angle<<" velocity="<<velocity<<std::endl;
1340    catchableObject->setObject(filename,"boy",position,size,velocity);
1341    _catchableObjects.push_back(catchableObject);
1342
1343    float r = (float)rand() / (float)RAND_MAX;
1344    if (r < _chanceOfExplodingAtStart)
1345    {
1346       catchableObject->explode();
1347    }
1348
1349    _gameGroup->addChild(catchableObject->_object.get());
1350}
1351
1352
1353class CompileStateCallback : public osgProducer::OsgCameraGroup::RealizeCallback
1354{
1355    public:
1356        CompileStateCallback(GameEventHandler* eh):_gameEventHandler(eh) {}
1357       
1358        virtual void operator()( osgProducer::OsgCameraGroup&, osgProducer::OsgSceneHandler& sh, const Producer::RenderSurface& )
1359        {
1360            // now safe to construct
1361            sh.init();
1362                       
1363            if (_gameEventHandler)
1364            {
1365                _gameEventHandler->compileGLObjects(*(sh.getSceneView()->getState()));
1366            }
1367        }
1368       
1369       
1370        GameEventHandler*  _gameEventHandler;
1371       
1372};
1373
1374int main( int argc, char **argv )
1375{
1376
1377    // use an ArgumentParser object to manage the program arguments.
1378    osg::ArgumentParser arguments(&argc,argv);
1379   
1380    // set up the usage document, in case we need to print out how to use this program.
1381    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
1382    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye");
1383    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in sceonds between the display of successive image pairs when in auto advance mode.");
1384    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
1385    arguments.getApplicationUsage()->addCommandLineOption("-x <float>","Horizontal offset of left and right images.");
1386    arguments.getApplicationUsage()->addCommandLineOption("-y <float>","Vertical offset of left and right images.");
1387    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
1388   
1389
1390    // construct the viewer.
1391    osgProducer::Viewer viewer(arguments);
1392
1393    // set up the value with sensible default event handlers.
1394    viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE);
1395
1396    // register the handler to add keyboard and mosue handling.
1397    GameEventHandler* seh = new GameEventHandler();
1398    viewer.getEventHandlerList().push_front(seh);
1399
1400    while (arguments.read("--boy")) seh->addPlayer(GameEventHandler::PLAYER_BOY);
1401    while (arguments.read("--girl")) seh->addPlayer(GameEventHandler::PLAYER_GIRL);
1402   
1403   
1404
1405    // get details on keyboard and mouse bindings used by the viewer.
1406    viewer.getUsage(*arguments.getApplicationUsage());
1407
1408    // if user request help write it out to cout.
1409    if (arguments.read("-h") || arguments.read("--help"))
1410    {
1411        arguments.getApplicationUsage()->write(std::cout);
1412        return 1;
1413    }
1414
1415    // any option left unread are converted into errors to write out later.
1416    arguments.reportRemainingOptionsAsUnrecognized();
1417
1418    // report any errors if they have occured when parsing the program aguments.
1419    if (arguments.errors())
1420    {
1421        arguments.writeErrorMessages(std::cout);
1422        return 1;
1423    }
1424   
1425    // now the windows have been realized we switch off the cursor to prevent it
1426    // distracting the people seeing the stereo images.
1427    float fovy = 1.0f;
1428    for( unsigned int i = 0; i < viewer.getNumberOfCameras(); i++ )
1429    {
1430        Producer::Camera* cam = viewer.getCamera(i);
1431        Producer::RenderSurface* rs = cam->getRenderSurface();
1432        rs->useCursor(false);
1433        fovy = osg::DegreesToRadians(cam->getLensVerticalFov());
1434    }
1435   
1436    seh->setFOVY(fovy);
1437   
1438    // enable the image cache so we don't need to keep loading the particle files
1439    osgDB::ReaderWriter::Options* options = new osgDB::ReaderWriter::Options;
1440    options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_IMAGES);
1441    osgDB::Registry::instance()->setOptions(options);
1442
1443
1444    // creat the scene from the file list.
1445    osg::ref_ptr<osg::Node> rootNode = seh->createScene();
1446
1447    //osgDB::writeNodeFile(*rootNode,"test.osg");
1448
1449    // set the scene to render
1450    viewer.setSceneData(rootNode.get());
1451
1452    viewer.setRealizeCallback(new CompileStateCallback(seh));
1453
1454    // create the windows and run the threads.
1455    viewer.realize();
1456   
1457    viewer.requestWarpPointer(0.5f,0.5f);
1458       
1459
1460    while( !viewer.done() )
1461    {
1462        // wait for all cull and draw threads to complete.
1463        viewer.sync();
1464
1465        // update the scene by traversing it with the the update visitor which will
1466        // call all node update callbacks and animations.
1467        viewer.update();
1468         
1469        viewer.setView(seh->getCameraPosition());
1470
1471        // fire off the cull and draw traversals of the scene.
1472        viewer.frame();
1473       
1474    }
1475   
1476    // run a clean up frame to delete all OpenGL objects.
1477    viewer.cleanup_frame();
1478
1479    // wait for all the clean up frame to complete.
1480    viewer.sync();
1481   
1482    return 0;
1483}
Note: See TracBrowser for help on using the browser.