diff --git a/Make/makedirdefs b/Make/makedirdefs index ece89e5a5..7abe28225 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -175,6 +175,7 @@ EXAMPLE_DIRS = \ osgbillboard\ osgblendequation\ osgcallback\ + osgcatch\ osgcameragroup\ osgclip\ osgcluster\ diff --git a/examples/osgcatch/GNUmakefile b/examples/osgcatch/GNUmakefile new file mode 100644 index 000000000..7c5e46468 --- /dev/null +++ b/examples/osgcatch/GNUmakefile @@ -0,0 +1,18 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgcatch.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + GNUmakefile.inst=GNUmakefile + +EXEC = osgcatch + +INC += $(X_INC) + +include $(TOPDIR)/Make/makerules + diff --git a/examples/osgcatch/GNUmakefile.inst b/examples/osgcatch/GNUmakefile.inst new file mode 100644 index 000000000..795ddf736 --- /dev/null +++ b/examples/osgcatch/GNUmakefile.inst @@ -0,0 +1,15 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgcatch.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgcatch + +INC += $(PRODUCER_INCLUDE_DIR) $(X_INC) +LDFLAGS += $(PRODUCER_LIB_DIR) + + +include $(TOPDIR)/Make/makerules diff --git a/examples/osgcatch/osgcatch.cpp b/examples/osgcatch/osgcatch.cpp new file mode 100644 index 000000000..e2eda8984 --- /dev/null +++ b/examples/osgcatch/osgcatch.cpp @@ -0,0 +1,515 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef std::vector FileList; + +struct Character +{ + Character(); + + void setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& orgin, const osg::Vec3& width, float positionRatio); + + void setLives(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives); + + void setCatches(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives); + + void moveLeft(); + void moveRight(); + void moveTo(float positionRatio); + + void reset(); + + bool addCatch(); + bool looseLife(); + + osg::Vec3 _origin; + osg::Vec3 _width; + + float _positionRatio; + osg::ref_ptr _character; + + unsigned int _numLives; + osg::ref_ptr _livesSwitch; + + unsigned int _numCatches; + osg::ref_ptr _catchSwitch; +}; + +Character::Character(): + _positionRatio(0.5f), + _numLives(3), + _numCatches(0) +{ +} + + +void Character::setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& origin, const osg::Vec3& width, float positionRatio) +{ + _origin = origin; + _width = width; + _positionRatio = positionRatio; + _numLives = 3; + _numCatches = 0; + + float _characterSize = _width.length()*0.2f; + + osg::Image* image = osgDB::readImageFile(filename); + if (image) + { + osg::Vec3 pos(-0.5f*_characterSize,0.0f,0.0); + osg::Vec3 width(_characterSize,0.0f,0.0); + osg::Vec3 height(0.0f,0.0f,_characterSize*((float)image->t())/(float)(image->s())); + + osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height); + osg::StateSet* stateset = geometry->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geometry); + + _character = new osg::PositionAttitudeTransform; + _character->setName(name); + _character->addChild(geode); + + moveTo(positionRatio); + } +} + +void Character::setLives(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numLives) +{ + float characterSize = delta.length(); + + _numLives = numLives; + _livesSwitch = new osg::Switch; + + osg::Image* image = osgDB::readImageFile(filename); + if (image) + { + osg::StateSet* stateset = _livesSwitch->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON); + + for(unsigned int i=0; it())/(float)(image->s())); + + osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geometry); + + _livesSwitch->addChild(geode,true); + + } + } + +} + +void Character::setCatches(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numCatches) +{ + float characterSize = delta.length(); + + _numCatches = 0; + _catchSwitch = new osg::Switch; + + osg::Image* image = osgDB::readImageFile(filename); + if (image) + { + osg::StateSet* stateset = _catchSwitch->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON); + + for(unsigned int i=0; it())/(float)(image->s())); + + osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geometry); + + _catchSwitch->addChild(geode,false); + + } + } + +} + +void Character::moveLeft() +{ + moveTo(_positionRatio - 0.01f); +} + +void Character::moveRight() +{ + moveTo(_positionRatio + 0.01f); +} + +void Character::moveTo(float positionRatio) +{ + if (positionRatio<0.0f) positionRatio = 0.0f; + if (positionRatio>1.0f) positionRatio = 1.0f; + + _positionRatio = positionRatio; + _character->setPosition(_origin+_width*+positionRatio); +} + +void Character::reset() +{ + _numCatches = 0; + _numLives = _livesSwitch->getNumChildren(); + + _livesSwitch->setAllChildrenOn(); + _catchSwitch->setAllChildrenOff(); +} + +bool Character::addCatch() +{ + if (!_catchSwitch || _numCatches>=_catchSwitch->getNumChildren()) return false; + + _catchSwitch->setValue(_numCatches,true); + ++_numCatches; + + return true; +} + +bool Character::looseLife() +{ + if (!_livesSwitch || _numLives==0) return true; + + --_numLives; + _livesSwitch->setValue(_numLives,false); + + return (_numLives==0); +} + + +class SlideEventHandler : public osgGA::GUIEventHandler +{ +public: + + SlideEventHandler(); + + META_Object(osgStereImageApp,SlideEventHandler); + + virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); } + + virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&); + + virtual void getUsage(osg::ApplicationUsage& usage) const; + + osg::Matrix getCameraPosition(); + + osg::Node* createScene(); + + void setFOVY(float fovy) { _fovy = fovy; } + float getFOVY() const { return _fovy; } + + void setBackground(const std::string& background) { _backgroundImageFile = background; } + +protected: + + ~SlideEventHandler() {} + SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {} + + osg::Vec3 _origin; + osg::Vec3 _width; + osg::Vec3 _height; + osg::Vec3 _originBaseLine; + osg::Vec3 _widthBaseLine; + float _characterSize; + + float _fovy; + + std::string _backgroundImageFile; + + + + Character _player1; + Character _player2; + + + bool _leftKeyPressed; + bool _rightKeyPressed; + +}; + + + + +SlideEventHandler::SlideEventHandler() +{ + _origin.set(0.0f,0.0f,0.0f); + _width.set(1280.0f,0.0f,0.0f); + _height.set(0.0f,0.0f,1024.0f); + _widthBaseLine = _width*0.9f; + _originBaseLine = _origin+_width*0.5-_widthBaseLine*0.5f; + _characterSize = _width.length()*0.2f; + + _backgroundImageFile = "Images/land_shallow_topo_2048.jpg"; + + _leftKeyPressed=false; + _rightKeyPressed=false; +} + +bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) +{ + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::FRAME): + { + if (_leftKeyPressed) + { + _player2.moveLeft(); + } + + if (_rightKeyPressed) + { + _player2.moveRight(); + } + + } + case(osgGA::GUIEventAdapter::KEYDOWN): + { + if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left) + { + _leftKeyPressed=true; + return true; + } + else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right) + { + _rightKeyPressed=true; + return true; + } + else if (ea.getKey()=='1') + { + _player1.looseLife(); + _player1.addCatch(); + return true; + } + else if (ea.getKey()=='2') + { + _player2.looseLife(); + _player2.addCatch(); + return true; + } + else if (ea.getKey()==' ') + { + _player1.reset(); + _player2.reset(); + return true; + } + } + case(osgGA::GUIEventAdapter::KEYUP): + { + if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left) + { + _leftKeyPressed=false; + return true; + } + else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right) + { + _rightKeyPressed=false; + return true; + } + } + case(osgGA::GUIEventAdapter::DRAG): + case(osgGA::GUIEventAdapter::MOVE): + { + float px = (ea.getXnormalized()+1.0f)*0.5f; + + _player1.moveTo(px); + + return true; + } + + default: + return false; + } +} + +void SlideEventHandler::getUsage(osg::ApplicationUsage&) const +{ +} + +osg::Matrix SlideEventHandler::getCameraPosition() +{ + osg::Matrix cameraPosition; + osg::Vec3 center = _origin+(_width+_height)*0.5f; + + float distance = _height.length()/(2.0f*tanf(_fovy*0.5f)); + + cameraPosition.makeLookAt(center-osg::Vec3(0.0f,distance,0.0f),center,osg::Vec3(0.0f,0.0f,1.0f)); + return cameraPosition; +} + +osg::Node* SlideEventHandler::createScene() +{ + + + osg::Group* group = new osg::Group; + + _player1.setCharacter("Catch/girl.png","girl", _originBaseLine, _widthBaseLine, 0.4f); + _player1.setLives("Catch/girl.png",_originBaseLine, osg::Vec3(0.0f,0.0f,100.0f),3); + _player1.setCatches("Catch/a.JPG",_originBaseLine+osg::Vec3(200.0f,0.0f,0.0f), osg::Vec3(0.0f,0.0f,100.0f),10); + group->addChild(_player1._character.get()); + group->addChild(_player1._livesSwitch.get()); + group->addChild(_player1._catchSwitch.get()); + + _player2.setCharacter("Catch/boy.png","boy", _originBaseLine, _widthBaseLine, 0.4f); + _player2.setLives("Catch/boy.png",_originBaseLine+osg::Vec3(900.0f,0.0f,000.0f), osg::Vec3(0.0f,0.0f,100.0f),3); + _player2.setCatches("Catch/b.JPG",_originBaseLine+osg::Vec3(1100.0f,0.0f,0.0f), osg::Vec3(0.0f,0.0f,100.0f),10); + group->addChild(_player2._character.get()); + group->addChild(_player2._livesSwitch.get()); + group->addChild(_player2._catchSwitch.get()); + + + // background + { + osg::Image* image = osgDB::readImageFile(_backgroundImageFile); + if (image) + { + osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height); + osg::StateSet* stateset = geometry->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geometry); + + group->addChild(geode); + + } + } + + + return group; +} + + +int main( int argc, char **argv ) +{ + + // use an ArgumentParser object to manage the program arguments. + osg::ArgumentParser arguments(&argc,argv); + + // set up the usage document, in case we need to print out how to use this program. + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images."); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye"); + arguments.getApplicationUsage()->addCommandLineOption("-d ","Time delay in sceonds between the display of successive image pairs when in auto advance mode."); + arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up."); + arguments.getApplicationUsage()->addCommandLineOption("-x ","Horizontal offset of left and right images."); + arguments.getApplicationUsage()->addCommandLineOption("-y ","Vertical offset of left and right images."); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); + + + // construct the viewer. + osgProducer::Viewer viewer(arguments); + + // set up the value with sensible default event handlers. + viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE); + + // register the handler to add keyboard and mosue handling. + SlideEventHandler* seh = new SlideEventHandler(); + viewer.getEventHandlerList().push_front(seh); + + std::string filename; + if (arguments.read("-b",filename)) + { + seh->setBackground(filename); + } + + + // get details on keyboard and mouse bindings used by the viewer. + viewer.getUsage(*arguments.getApplicationUsage()); + + // if user request help write it out to cout. + if (arguments.read("-h") || arguments.read("--help")) + { + arguments.getApplicationUsage()->write(std::cout); + return 1; + } + + // any option left unread are converted into errors to write out later. + arguments.reportRemainingOptionsAsUnrecognized(); + + // report any errors if they have occured when parsing the program aguments. + if (arguments.errors()) + { + arguments.writeErrorMessages(std::cout); + return 1; + } + + // now the windows have been realized we switch off the cursor to prevent it + // distracting the people seeing the stereo images. + float fovy = 1.0f; + for( unsigned int i = 0; i < viewer.getCameraConfig()->getNumberOfCameras(); i++ ) + { + Producer::Camera* cam = viewer.getCameraConfig()->getCamera(i); + Producer::RenderSurface* rs = cam->getRenderSurface(); + rs->useCursor(false); + fovy = osg::DegreesToRadians(cam->getLensVerticalFov()); + } + + seh->setFOVY(fovy); + + // creat the scene from the file list. + osg::ref_ptr rootNode = seh->createScene(); + + osgDB::writeNodeFile(*rootNode,"test.osg"); + + // set the scene to render + viewer.setSceneData(rootNode.get()); + + // create the windows and run the threads. + viewer.realize(); + + viewer.requestWarpPointer(0.5f,0.5f); + + + while( !viewer.done() ) + { + // wait for all cull and draw threads to complete. + viewer.sync(); + + // update the scene by traversing it with the the update visitor which will + // call all node update callbacks and animations. + viewer.update(); + + viewer.setView(seh->getCameraPosition()); + + // fire off the cull and draw traversals of the scene. + viewer.frame(); + + } + + // wait for all cull and draw threads to complete before exit. + viewer.sync(); + + return 0; +} +