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

Revision 6160, 47.6 kB (checked in by robert, 10 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.