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

Revision 6160, 47.6 kB (checked in by robert, 8 years ago)

Added setDataVariance(DYNAMIC) to the scores text entires to prevent the
DrawThreadPerContext? for crashing due to double buffering of dynamic data.

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