diff --git a/Make/makedirdefs b/Make/makedirdefs index c75091e41..e4887a4ec 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -153,7 +153,7 @@ EXAMPLE_DIRS = \ osgpagedlod\ osgpick\ osgpoints\ -# osgphotoalbum\ + osgphotoalbum\ osgprerender\ osgprerendercubemap\ osgreflect\ diff --git a/examples/osgphotoalbum/GNUmakefile b/examples/osgphotoalbum/GNUmakefile new file mode 100644 index 000000000..9047e33e7 --- /dev/null +++ b/examples/osgphotoalbum/GNUmakefile @@ -0,0 +1,18 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgphotoalbum.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + GNUmakefile.inst=GNUmakefile + +EXEC = osgphotoalbum + +INC += $(X_INC) + +include $(TOPDIR)/Make/makerules + diff --git a/examples/osgphotoalbum/GNUmakefile.inst b/examples/osgphotoalbum/GNUmakefile.inst new file mode 100644 index 000000000..30349d277 --- /dev/null +++ b/examples/osgphotoalbum/GNUmakefile.inst @@ -0,0 +1,15 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgphotoalbum.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgphotoalbum + +INC += $(PRODUCER_INCLUDE_DIR) $(X_INC) +LDFLAGS += $(PRODUCER_LIB_DIR) + + +include $(TOPDIR)/Make/makerules diff --git a/examples/osgphotoalbum/osgphotoalbum.cpp b/examples/osgphotoalbum/osgphotoalbum.cpp new file mode 100644 index 000000000..27451bd5d --- /dev/null +++ b/examples/osgphotoalbum/osgphotoalbum.cpp @@ -0,0 +1,535 @@ +/* -*-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 +#include + +#include + +#include + +class ImageReaderWriter : public osgDB::ReaderWriter +{ + public: + virtual const char* className() { return "Image Reader"; } + + + struct DataReference + { + DataReference(): + _fileName(), + _resolutionX(256), + _resolutionY(256), + _center(0.0f,0.0f,0.0f), + _maximumWidth(1.25f,0.0f,0.0f), + _maximumHeight(0.0f,0.0f,1.0f), + _numPointsAcross(10), + _numPointsUp(10) {} + + DataReference(const std::string& fileName, unsigned int res): + _fileName(fileName), + _resolutionX(res), + _resolutionY(res), + _center(0.0f,0.0f,0.0f), + _maximumWidth(1.25f,0.0f,0.0f), + _maximumHeight(0.0f,0.0f,1.0f), + _numPointsAcross(10), + _numPointsUp(10) {} + + DataReference(const DataReference& rhs): + _fileName(rhs._fileName), + _resolutionX(rhs._resolutionX), + _resolutionY(rhs._resolutionY), + _center(rhs._center), + _maximumWidth(rhs._maximumWidth), + _maximumHeight(rhs._maximumHeight), + _numPointsAcross(rhs._numPointsAcross), + _numPointsUp(rhs._numPointsUp) {} + + std::string _fileName; + unsigned int _resolutionX; + unsigned int _resolutionY; + osg::Vec3 _center; + osg::Vec3 _maximumWidth; + osg::Vec3 _maximumHeight; + unsigned int _numPointsAcross; + unsigned int _numPointsUp; + }; + + typedef std::map DataReferenceMap; + DataReferenceMap _dataReferences; + + std::string insertReference(const std::string& fileName, unsigned int res) + { + std::stringstream ostr; + ostr<<"res_"<second; + + // record previous options. + osg::ref_ptr previousOptions = osgDB::Registry::instance()->getOptions(); + + osg::ref_ptr options = new osgDB::ImageOptions; + options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW; + options->_destinationPixelWindow.set(0,0,dr._resolutionX,dr._resolutionY); + + osgDB::Registry::instance()->setOptions(options.get()); + + osg::Image* image = osgDB::readImageFile(dr._fileName); + + // restore previous options. + osgDB::Registry::instance()->setOptions(previousOptions.get()); + + if (image) + { + + float s = options.valid()?options->_sourcePixelWindow.windowWidth:1.0f; + float t = options.valid()?options->_sourcePixelWindow.windowHeight:1.0f; + + osg::Geode* geode = osg::createGeodeForImage(image,s,t); + return geode; + + } + else + { + return 0; + } + + + } + +}; + + +// now register with Registry to instantiate the above +// reader/writer. +osgDB::RegisterReaderWriterProxy g_ImageReaderWriter; + + + +typedef std::vector FileList; + +class SlideEventHandler : public osgGA::GUIEventHandler, public osg::NodeCallback +{ +public: + + SlideEventHandler(); + + META_Object(osgStereImageApp,SlideEventHandler); + + void set(osg::Switch* sw, float timePerSlide, bool autoSteppingActive); + + 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; + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + + void nextSlide(); + + void previousSlide(); + +protected: + + ~SlideEventHandler() {} + SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {} + + osg::ref_ptr _switch; + bool _firstTraversal; + unsigned int _activeSlide; + double _previousTime; + double _timePerSlide; + bool _autoSteppingActive; +}; + +SlideEventHandler::SlideEventHandler(): + _switch(0), + _firstTraversal(true), + _activeSlide(0), + _previousTime(-1.0f), + _timePerSlide(5.0), + _autoSteppingActive(false) +{ +} + +void SlideEventHandler::set(osg::Switch* sw, float timePerSlide, bool autoSteppingActive) +{ + _switch = sw; + _switch->setUpdateCallback(this); + + _timePerSlide = timePerSlide; + _autoSteppingActive = autoSteppingActive; + +} + +bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) +{ + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::KEYDOWN): + { + if (ea.getKey()=='a') + { + _autoSteppingActive = !_autoSteppingActive; + _previousTime = ea.time(); + return true; + } + else if (ea.getKey()=='n') + { + nextSlide(); + return true; + } + else if (ea.getKey()=='p') + { + previousSlide(); + return true; + } + return false; + } + + default: + return false; + } +} + +void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const +{ + usage.addKeyboardMouseBinding("Space","Reset the image position to center"); + usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image"); + usage.addKeyboardMouseBinding("n","Advance to next image"); + usage.addKeyboardMouseBinding("p","Move to previous image"); +} + +void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv) +{ + if (_autoSteppingActive && nv->getFrameStamp()) + { + double time = nv->getFrameStamp()->getReferenceTime(); + + if (_firstTraversal) + { + _firstTraversal = false; + _previousTime = time; + } + else if (time-_previousTime>_timePerSlide) + { + _previousTime = time; + + nextSlide(); + } + + } + + traverse(node,nv); +} + +void SlideEventHandler::nextSlide() +{ + if (_switch->getNumChildren()==0) return; + + ++_activeSlide; + if (_activeSlide>=_switch->getNumChildren()) _activeSlide = 0; + + _switch->setSingleChildOn(_activeSlide); +} + +void SlideEventHandler::previousSlide() +{ + if (_switch->getNumChildren()==0) return; + + if (_activeSlide==0) _activeSlide = _switch->getNumChildren()-1; + else --_activeSlide; + + _switch->setSingleChildOn(_activeSlide); +} + +// create a switch containing a set of child each containing a +// stereo image pair. +osg::Switch* createScene(const FileList& fileList, float height, float length) +{ + osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal"); + if (!readerWriter) + { + std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"< > NodeList; + NodeList nodes; + + // load the images. + unsigned int i; + for(i=0;isetFont("fonts/arial.ttf"); + text->setPosition(center); + text->setCharacterSize(0.1f); + text->setAlignment(osgText::Text::CENTER_CENTER); + text->setAxisAlignment(osgText::Text::XZ_PLANE); + text->setText(fileList[i]); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(text); + + osg::PagedLOD* pagedlod = new osg::PagedLOD; + pagedlod->setCenter(center); + pagedlod->setRadius(1.6f); + pagedlod->setNumChildrenThatCannotBeExpired(2); + + pagedlod->setRange(0,max_visible_distance,1e7); + pagedlod->addChild(geode); + + pagedlod->setRange(1,cut_off_distance,max_visible_distance); + pagedlod->setFileName(1,rw->insertReference(fileList[i],128)); + + pagedlod->setRange(2,0.0f,cut_off_distance); + pagedlod->setFileName(2,rw->insertReference(fileList[i],1024)); + + nodes.push_back(pagedlod); + } + + + if (nodes.empty()) return 0; + + osg::Group* front = new osg::Group; + sw->addChild(front); + + unsigned int nodes_across = (unsigned int)ceilf(sqrtf((float)nodes.size()*1.25)); + unsigned int nodes_down = (unsigned int)ceilf((float)nodes.size()/(float)nodes_across); + + float scale = 1.0f/(float)nodes_down; + + osg::Vec3 down_delta(0.0f,0.0f,-scale); + osg::Vec3 across_delta(scale*1.25,0.0f,0.0f); + osg::Vec3 leftMargin(-down_delta*((float)nodes_down*0.5f)-across_delta*((float)nodes_across*0.5f)); + + osg::Vec3 pos = leftMargin; + i=0; + + // front cover background + { + osg::Geometry* geometry = createTexturedQuadGeometry(osg::Vec3(-1.25f,0.0f,-1.0f),osg::Vec3(2.5f,0.0f,0.0f),osg::Vec3(0.0f,0.0f,2.0f)); + osg::Geode* background = new osg::Geode; + background->addDrawable(geometry); + front->addChild(background); + + osg::StateSet* stateset = geometry->getOrCreateStateSet(); + stateset->setAttributeAndModes(new osg::PolygonOffset(2.0f,2.0f),osg::StateAttribute::ON); + stateset->setTextureAttributeAndModes(0,new osg::Texture2D(osgDB::readImageFile("lz.rgb")),osg::StateAttribute::ON); + } + + NodeList::iterator itr; + for(itr=nodes.begin(); + itr!=nodes.end(); + ++itr) + { + osg::MatrixTransform* mt = new osg::MatrixTransform; + mt->setMatrix(osg::Matrix::scale(scale*0.45f,scale*0.45f,scale*0.45f)*osg::Matrix::translate(pos)); + mt->addChild(itr->get()); + front->addChild(mt); + + i++; + if ((i%nodes_across)==0) + { + leftMargin += down_delta; + pos = leftMargin; + } + else pos += across_delta; + } + + + for(itr=nodes.begin(); + itr!=nodes.end(); + ++itr) + { + sw->addChild(itr->get()); + } + + if (sw->getNumChildren()>0) + { + // select first child. + sw->setSingleChildOn(0); + } + + return sw; +} + +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 [image_file]"); + 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("-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); + viewer.setUpViewer(); + + // register the handler to add keyboard and mosue handling. + SlideEventHandler* seh = new SlideEventHandler(); + viewer.getEventHandlerList().push_front(seh); + + + // get details on keyboard and mouse bindings used by the viewer. + viewer.getUsage(*arguments.getApplicationUsage()); + + // read any time delay argument. + float timeDelayBetweenSlides = 5.0f; + while (arguments.read("-d",timeDelayBetweenSlides)) {} + + bool autoSteppingActive = false; + while (arguments.read("-a")) autoSteppingActive = true; + + // 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; + } + + if (arguments.argc()<=1) + { + arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); + return 1; + } + + // extract the filenames from the arguments list. + FileList fileList; + for(int pos=1;posgetNumberOfCameras(); i++ ) + { + Producer::Camera* cam = viewer.getCameraConfig()->getCamera(i); + Producer::RenderSurface* rs = cam->getRenderSurface(); + rs->useCursor(false); + fovy = cam->getLensVerticalFov(); + } + + float radius = 1.0f; + float height = 2*radius*tan(fovy*0.5f); + float length = osg::PI*radius; // half a cylinder. + + // creat the scene from the file list. + osg::ref_ptr rootNode = createScene(fileList,height,length); + + if (!rootNode) return 0; + + + //osgDB::writeNodeFile(*rootNode,"test.osg"); + + // set the scene to render + viewer.setSceneData(rootNode.get()); + + + // set up the SlideEventHandler. + seh->set(rootNode.get(),timeDelayBetweenSlides,autoSteppingActive); + + + // create the windows and run the threads. + viewer.realize(); + + osg::Matrix homePosition; + homePosition.makeLookAt(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(0.0f,1.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f)); + + 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(homePosition); + + // 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; +} +