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

Revision 12529, 48.2 kB (checked in by robert, 3 years ago)

Replaced .osg with .osgt file usage

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