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

Revision 3974, 15.0 kB (checked in by robert, 10 years ago)

Beginnings of litte kiddies game example, written in collaboration with my
5 year old daughter who is the game designer and artist on this little task :)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgProducer/Viewer>
15#include <osgDB/ReadFile>
16#include <osgDB/WriteFile>
17#include <osgUtil/Optimizer>
18
19#include <osg/Geode>
20#include <osg/Notify>
21#include <osg/MatrixTransform>
22#include <osg/PositionAttitudeTransform>
23#include <osg/Switch>
24#include <osg/TexMat>
25#include <osg/Texture2D>
26
27typedef std::vector<std::string> FileList;
28
29struct Character
30{
31    Character();
32   
33    void setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& orgin, const osg::Vec3& width, float positionRatio);
34   
35    void setLives(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives);
36   
37    void setCatches(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives);
38
39    void moveLeft();
40    void moveRight();
41    void moveTo(float positionRatio);
42
43    void reset();
44
45    bool addCatch();
46    bool looseLife();
47
48    osg::Vec3 _origin;
49    osg::Vec3 _width;
50
51    float                                        _positionRatio;
52    osg::ref_ptr<osg::PositionAttitudeTransform> _character;
53
54    unsigned int                                 _numLives;
55    osg::ref_ptr<osg::Switch>                    _livesSwitch;
56
57    unsigned int                                 _numCatches;
58    osg::ref_ptr<osg::Switch>                    _catchSwitch;
59};
60
61Character::Character():
62    _positionRatio(0.5f),
63    _numLives(3),
64    _numCatches(0)
65{
66}
67
68
69void Character::setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& origin, const osg::Vec3& width, float positionRatio)
70{
71    _origin = origin;
72    _width = width;
73    _positionRatio = positionRatio;
74    _numLives = 3;
75    _numCatches = 0;
76
77    float _characterSize = _width.length()*0.2f;
78
79    osg::Image* image = osgDB::readImageFile(filename);
80    if (image)
81    {
82        osg::Vec3 pos(-0.5f*_characterSize,0.0f,0.0);
83        osg::Vec3 width(_characterSize,0.0f,0.0);
84        osg::Vec3 height(0.0f,0.0f,_characterSize*((float)image->t())/(float)(image->s()));
85
86        osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
87        osg::StateSet* stateset = geometry->getOrCreateStateSet();
88        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
89
90        osg::Geode* geode = new osg::Geode;
91        geode->addDrawable(geometry);
92
93        _character = new osg::PositionAttitudeTransform;
94        _character->setName(name);
95        _character->addChild(geode);
96       
97        moveTo(positionRatio);
98    }
99}
100
101void Character::setLives(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numLives)
102{
103    float characterSize = delta.length();
104
105    _numLives = numLives;
106    _livesSwitch = new osg::Switch;
107
108    osg::Image* image = osgDB::readImageFile(filename);
109    if (image)
110    {
111        osg::StateSet* stateset = _livesSwitch->getOrCreateStateSet();
112        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
113
114        for(unsigned int i=0; i<numLives; ++i)
115        {
116            osg::Vec3 pos = origin + delta*(float)i;
117            osg::Vec3 width(characterSize,0.0f,0.0);
118            osg::Vec3 height(0.0f,0.0f,characterSize*((float)image->t())/(float)(image->s()));
119
120            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
121
122            osg::Geode* geode = new osg::Geode;
123            geode->addDrawable(geometry);
124
125            _livesSwitch->addChild(geode,true);
126
127        }
128    }
129
130}
131
132void Character::setCatches(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numCatches)
133{
134    float characterSize = delta.length();
135
136    _numCatches = 0;
137    _catchSwitch = new osg::Switch;
138
139    osg::Image* image = osgDB::readImageFile(filename);
140    if (image)
141    {
142        osg::StateSet* stateset = _catchSwitch->getOrCreateStateSet();
143        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
144
145        for(unsigned int i=0; i<numCatches; ++i)
146        {
147            osg::Vec3 pos = origin + delta*(float)i;
148            osg::Vec3 width(characterSize,0.0f,0.0);
149            osg::Vec3 height(0.0f,0.0f,characterSize*((float)image->t())/(float)(image->s()));
150
151            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
152
153            osg::Geode* geode = new osg::Geode;
154            geode->addDrawable(geometry);
155
156            _catchSwitch->addChild(geode,false);
157
158        }
159    }
160
161}
162
163void Character::moveLeft()
164{
165    moveTo(_positionRatio - 0.01f);
166}
167
168void Character::moveRight()
169{
170    moveTo(_positionRatio + 0.01f);
171}
172
173void Character::moveTo(float positionRatio)
174{
175    if (positionRatio<0.0f) positionRatio = 0.0f;
176    if (positionRatio>1.0f) positionRatio = 1.0f;
177
178    _positionRatio = positionRatio;
179    _character->setPosition(_origin+_width*+positionRatio);
180}
181
182void Character::reset()
183{
184    _numCatches = 0;
185    _numLives = _livesSwitch->getNumChildren();
186
187    _livesSwitch->setAllChildrenOn();
188    _catchSwitch->setAllChildrenOff();
189}
190
191bool Character::addCatch()
192{
193    if (!_catchSwitch || _numCatches>=_catchSwitch->getNumChildren()) return false;
194   
195    _catchSwitch->setValue(_numCatches,true);
196    ++_numCatches;
197   
198    return true;
199}
200
201bool Character::looseLife()
202{
203    if (!_livesSwitch || _numLives==0) return true;
204   
205    --_numLives;
206    _livesSwitch->setValue(_numLives,false);
207   
208    return (_numLives==0);
209}
210
211
212class SlideEventHandler : public osgGA::GUIEventHandler
213{
214public:
215
216    SlideEventHandler();
217   
218    META_Object(osgStereImageApp,SlideEventHandler);
219
220    virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }
221
222    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
223   
224    virtual void getUsage(osg::ApplicationUsage& usage) const;
225   
226    osg::Matrix getCameraPosition();
227   
228    osg::Node* createScene();
229   
230    void setFOVY(float fovy) { _fovy = fovy; }
231    float getFOVY() const { return _fovy; }
232   
233    void setBackground(const std::string& background) { _backgroundImageFile = background; }
234
235protected:
236
237    ~SlideEventHandler() {}
238    SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {}
239
240    osg::Vec3 _origin;
241    osg::Vec3 _width;
242    osg::Vec3 _height;
243    osg::Vec3 _originBaseLine;
244    osg::Vec3 _widthBaseLine;
245    float     _characterSize;
246   
247    float _fovy;
248   
249    std::string _backgroundImageFile;
250
251
252   
253    Character _player1;
254    Character _player2;
255
256
257    bool _leftKeyPressed;
258    bool _rightKeyPressed;   
259       
260};
261
262
263
264
265SlideEventHandler::SlideEventHandler()
266{
267    _origin.set(0.0f,0.0f,0.0f);
268    _width.set(1280.0f,0.0f,0.0f);
269    _height.set(0.0f,0.0f,1024.0f);
270    _widthBaseLine = _width*0.9f;
271    _originBaseLine = _origin+_width*0.5-_widthBaseLine*0.5f;
272    _characterSize = _width.length()*0.2f;
273
274    _backgroundImageFile = "Images/land_shallow_topo_2048.jpg";
275
276    _leftKeyPressed=false;
277    _rightKeyPressed=false;
278}
279
280bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
281{
282    switch(ea.getEventType())
283    {
284        case(osgGA::GUIEventAdapter::FRAME):
285        {
286            if (_leftKeyPressed)
287            {
288                _player2.moveLeft();
289            }
290           
291            if (_rightKeyPressed)
292            {
293                _player2.moveRight();
294            }
295           
296        }
297        case(osgGA::GUIEventAdapter::KEYDOWN):
298        {
299            if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
300            {
301                _leftKeyPressed=true;
302                return true;
303            }
304            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
305            {
306                _rightKeyPressed=true;
307                return true;
308            }
309            else if (ea.getKey()=='1')
310            {
311                _player1.looseLife();
312                _player1.addCatch();
313                return true;
314            }
315            else if (ea.getKey()=='2')
316            {
317                _player2.looseLife();
318                _player2.addCatch();
319                return true;
320            }
321            else if (ea.getKey()==' ')
322            {
323                _player1.reset();
324                _player2.reset();
325                return true;
326            }
327        }
328        case(osgGA::GUIEventAdapter::KEYUP):
329        {
330            if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
331            {
332                _leftKeyPressed=false;
333                return true;
334            }
335            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
336            {
337                _rightKeyPressed=false;
338                return true;
339            }
340        }
341        case(osgGA::GUIEventAdapter::DRAG):
342        case(osgGA::GUIEventAdapter::MOVE):
343        {
344            float px = (ea.getXnormalized()+1.0f)*0.5f;
345
346            _player1.moveTo(px);
347
348            return true;
349        }
350
351        default:
352            return false;
353    }
354}
355
356void SlideEventHandler::getUsage(osg::ApplicationUsage&) const
357{
358}
359
360osg::Matrix SlideEventHandler::getCameraPosition()
361{
362    osg::Matrix cameraPosition;
363    osg::Vec3 center = _origin+(_width+_height)*0.5f;
364   
365    float distance = _height.length()/(2.0f*tanf(_fovy*0.5f));
366   
367    cameraPosition.makeLookAt(center-osg::Vec3(0.0f,distance,0.0f),center,osg::Vec3(0.0f,0.0f,1.0f));
368    return cameraPosition;
369}
370
371osg::Node* SlideEventHandler::createScene()
372{
373
374
375    osg::Group* group = new osg::Group;
376   
377    _player1.setCharacter("Catch/girl.png","girl", _originBaseLine, _widthBaseLine, 0.4f);
378    _player1.setLives("Catch/girl.png",_originBaseLine, osg::Vec3(0.0f,0.0f,100.0f),3);
379    _player1.setCatches("Catch/a.JPG",_originBaseLine+osg::Vec3(200.0f,0.0f,0.0f), osg::Vec3(0.0f,0.0f,100.0f),10);
380    group->addChild(_player1._character.get());
381    group->addChild(_player1._livesSwitch.get());
382    group->addChild(_player1._catchSwitch.get());
383
384    _player2.setCharacter("Catch/boy.png","boy", _originBaseLine, _widthBaseLine, 0.4f);
385    _player2.setLives("Catch/boy.png",_originBaseLine+osg::Vec3(900.0f,0.0f,000.0f), osg::Vec3(0.0f,0.0f,100.0f),3);
386    _player2.setCatches("Catch/b.JPG",_originBaseLine+osg::Vec3(1100.0f,0.0f,0.0f), osg::Vec3(0.0f,0.0f,100.0f),10);
387    group->addChild(_player2._character.get());
388    group->addChild(_player2._livesSwitch.get());
389    group->addChild(_player2._catchSwitch.get());
390
391   
392    // background
393    {
394        osg::Image* image = osgDB::readImageFile(_backgroundImageFile);
395        if (image)
396        {
397            osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
398            osg::StateSet* stateset = geometry->getOrCreateStateSet();
399            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
400           
401            osg::Geode* geode = new osg::Geode;
402            geode->addDrawable(geometry);
403
404            group->addChild(geode);
405           
406        }
407    }
408
409
410    return group;
411}
412
413
414int main( int argc, char **argv )
415{
416
417    // use an ArgumentParser object to manage the program arguments.
418    osg::ArgumentParser arguments(&argc,argv);
419   
420    // set up the usage document, in case we need to print out how to use this program.
421    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
422    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye");
423    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in sceonds between the display of successive image pairs when in auto advance mode.");
424    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
425    arguments.getApplicationUsage()->addCommandLineOption("-x <float>","Horizontal offset of left and right images.");
426    arguments.getApplicationUsage()->addCommandLineOption("-y <float>","Vertical offset of left and right images.");
427    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
428   
429
430    // construct the viewer.
431    osgProducer::Viewer viewer(arguments);
432
433    // set up the value with sensible default event handlers.
434    viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE);
435
436    // register the handler to add keyboard and mosue handling.
437    SlideEventHandler* seh = new SlideEventHandler();
438    viewer.getEventHandlerList().push_front(seh);
439
440    std::string filename;
441    if (arguments.read("-b",filename))
442    {
443        seh->setBackground(filename);
444    }
445
446
447    // get details on keyboard and mouse bindings used by the viewer.
448    viewer.getUsage(*arguments.getApplicationUsage());
449
450    // if user request help write it out to cout.
451    if (arguments.read("-h") || arguments.read("--help"))
452    {
453        arguments.getApplicationUsage()->write(std::cout);
454        return 1;
455    }
456
457    // any option left unread are converted into errors to write out later.
458    arguments.reportRemainingOptionsAsUnrecognized();
459
460    // report any errors if they have occured when parsing the program aguments.
461    if (arguments.errors())
462    {
463        arguments.writeErrorMessages(std::cout);
464        return 1;
465    }
466   
467    // now the windows have been realized we switch off the cursor to prevent it
468    // distracting the people seeing the stereo images.
469    float fovy = 1.0f;
470    for( unsigned int i = 0; i < viewer.getCameraConfig()->getNumberOfCameras(); i++ )
471    {
472        Producer::Camera* cam = viewer.getCameraConfig()->getCamera(i);
473        Producer::RenderSurface* rs = cam->getRenderSurface();
474        rs->useCursor(false);
475        fovy = osg::DegreesToRadians(cam->getLensVerticalFov());
476    }
477   
478    seh->setFOVY(fovy);
479   
480    // creat the scene from the file list.
481    osg::ref_ptr<osg::Node> rootNode = seh->createScene();
482
483    osgDB::writeNodeFile(*rootNode,"test.osg");
484
485    // set the scene to render
486    viewer.setSceneData(rootNode.get());
487
488    // create the windows and run the threads.
489    viewer.realize();
490   
491    viewer.requestWarpPointer(0.5f,0.5f);
492       
493
494    while( !viewer.done() )
495    {
496        // wait for all cull and draw threads to complete.
497        viewer.sync();
498
499        // update the scene by traversing it with the the update visitor which will
500        // call all node update callbacks and animations.
501        viewer.update();
502         
503        viewer.setView(seh->getCameraPosition());
504
505        // fire off the cull and draw traversals of the scene.
506        viewer.frame();
507       
508    }
509   
510    // wait for all cull and draw threads to complete before exit.
511    viewer.sync();
512   
513    return 0;
514}
Note: See TracBrowser for help on using the browser.