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

Revision 5890, 51.8 kB (checked in by robert, 7 years ago)

Removed the setting of thread safe ref/unref and max number of graphics contexts
as this is now done automatically by osgViewer::Viewer

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