diff --git a/examples/osgstereoimage/osgstereoimage.cpp b/examples/osgstereoimage/osgstereoimage.cpp index cbb5355be..96f500ead 100644 --- a/examples/osgstereoimage/osgstereoimage.cpp +++ b/examples/osgstereoimage/osgstereoimage.cpp @@ -32,6 +32,121 @@ typedef std::vector FileList; +osg::Geode* createSectorForImage(osg::Image* image, osg::TexMat* texmat, float s,float t, float radius, float height, float length) +{ + + int numSegments = 20; + float Theta = length/radius; + float dTheta = Theta/(float)(numSegments-1); + + float ThetaZero = height*s/(t*radius); + + // set up the texture. + osg::Texture2D* texture = new osg::Texture2D; + texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + texture->setResizeNonPowerOfTwoHint(false); + texture->setImage(image); + + // set up the drawstate. + osg::StateSet* dstate = new osg::StateSet; + dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); + dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); + dstate->setTextureAttribute(0, texmat); + + // set up the geoset. + osg::Geometry* geom = new osg::Geometry; + geom->setStateSet(dstate); + + osg::Vec3Array* coords = new osg::Vec3Array(); + osg::Vec2Array* tcoords = new osg::Vec2Array(); + + int i; + float angle = -Theta/2.0f; + for(i=0; + ipush_back(osg::Vec3(sinf(angle)*radius,cosf(angle)*radius,height*0.5f)); // top + coords->push_back(osg::Vec3(sinf(angle)*radius,cosf(angle)*radius,-height*0.5f)); // bottom. + + tcoords->push_back(osg::Vec2(angle/ThetaZero+0.5f,1.0f)); // top + tcoords->push_back(osg::Vec2(angle/ThetaZero+0.5f,0.0f)); // bottom. + + } + + osg::Vec4Array* colors = new osg::Vec4Array(); + colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + + osg::DrawArrays* elements = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,coords->size()); + + + + geom->setVertexArray(coords); + geom->setTexCoordArray(0,tcoords); + geom->setColorArray(colors); + geom->setColorBinding(osg::Geometry::BIND_OVERALL); + + geom->addPrimitiveSet(elements); + + // set up the geode. + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geom); + + return geode; + +} + +osg::Group * loadImages(std::string image1, std::string image2, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length) { + osg::ref_ptr imageLeft = osgDB::readImageFile(image1); + osg::ref_ptr imageRight = osgDB::readImageFile(image2); + if (imageLeft.valid() && imageRight.valid()) + { + float average_s = (imageLeft->s()+imageRight->s())*0.5f; + float average_t = (imageLeft->t()+imageRight->t())*0.5f; + osg::Geode* geodeLeft = createSectorForImage(imageLeft.get(),texmatLeft,average_s,average_t, radius, height, length); + geodeLeft->setNodeMask(0x01); + + osg::Geode* geodeRight = createSectorForImage(imageRight.get(),texmatRight,average_s,average_t, radius, height, length); + geodeRight->setNodeMask(0x02); + + osg::Group * imageGroup = new osg::Group; + + imageGroup->addChild(geodeLeft); + imageGroup->addChild(geodeRight); + return imageGroup; + } + else + { + std::cout << "Warning: Unable to load both image files, '"<addChild(imageGroup); + } + + + if (sw->getNumChildren()>0) + { + // select first child. + sw->setSingleChildOn(0); + } + + return sw; +} + class SlideEventHandler : public osgGA::GUIEventHandler { public: @@ -43,6 +158,9 @@ public: void set(osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float timePerSlide, bool autoSteppingActive); + void set(FileList fileList, osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length, float timePerSlide, bool autoSteppingActive); + + virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&); virtual void getUsage(osg::ApplicationUsage& usage) const; @@ -69,6 +187,9 @@ protected: osg::ref_ptr _switch; osg::ref_ptr _texmatLeft; osg::ref_ptr _texmatRight; + float _radius; + float _height; + float _length; bool _firstTraversal; unsigned int _activeSlide; double _previousTime; @@ -78,6 +199,7 @@ protected: float _currentSeperationX; float _initSeperationY; float _currentSeperationY; + FileList _fileList; }; @@ -114,6 +236,35 @@ void SlideEventHandler::set(osg::Switch* sw, float offsetX, float offsetY, osg:: } +void SlideEventHandler::set(FileList fileList, osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length, float timePerSlide, bool autoSteppingActive) +{ + _switch = sw; + _switch->setUpdateCallback(this); + _fileList=FileList(fileList); + + osg::ref_ptr imageGroup = loadImages(fileList[0],fileList[1],texmatLeft,texmatRight, radius, height, length); + if (imageGroup.get())_switch->addChild(imageGroup.get()); + + _texmatLeft = texmatLeft; + _texmatRight = texmatRight; + + _radius=radius; + _height=height; + _length=length; + + _timePerSlide = timePerSlide; + _autoSteppingActive = autoSteppingActive; + + _initSeperationX = offsetX; + _currentSeperationX = _initSeperationX; + + _initSeperationY = offsetY; + _currentSeperationY = _initSeperationY; + + initTexMatrices(); +} + + bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) { switch(ea.getEventType()) @@ -234,22 +385,38 @@ void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv) void SlideEventHandler::nextSlide() { + if (_switch->getNumChildren()==0) return; ++_activeSlide; - if (_activeSlide>=_switch->getNumChildren()) _activeSlide = 0; - _switch->setSingleChildOn(_activeSlide); + if (_fileList.size()>0) { + if (_activeSlide>= _fileList.size()/2 ) _activeSlide = 0; + osg::ref_ptr images = loadImages(_fileList[2*_activeSlide],_fileList[2*_activeSlide+1],_texmatLeft.get(),_texmatRight.get(),_radius,_height,_length); + if (images.valid()) _switch->replaceChild(_switch->getChild(0),images.get()); + + } else { + 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; + if (_fileList.size()>0) { + if (_activeSlide==0) _activeSlide = _fileList.size()/2-1; + else --_activeSlide; + osg::ref_ptr images = loadImages(_fileList[2*_activeSlide],_fileList[2*_activeSlide+1],_texmatLeft.get(),_texmatRight.get(),_radius,_height,_length); + if (images.valid()) _switch->replaceChild(_switch->getChild(0),images.get()); + } else { + if (_activeSlide==0) _activeSlide = _switch->getNumChildren()-1; + else --_activeSlide; - _switch->setSingleChildOn(_activeSlide); + _switch->setSingleChildOn(_activeSlide); + } } void SlideEventHandler::scaleImage(float s) @@ -281,115 +448,6 @@ void SlideEventHandler::initTexMatrices() } -osg::Geode* createSectorForImage(osg::Image* image, osg::TexMat* texmat, float s,float t, float radius, float height, float length) -{ - - int numSegments = 20; - float Theta = length/radius; - float dTheta = Theta/(float)(numSegments-1); - - float ThetaZero = height*s/(t*radius); - - // set up the texture. - osg::Texture2D* texture = new osg::Texture2D; - texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); - texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); - texture->setImage(image); - - // set up the drawstate. - osg::StateSet* dstate = new osg::StateSet; - dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); - dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF); - dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); - dstate->setTextureAttribute(0, texmat); - - // set up the geoset. - osg::Geometry* geom = new osg::Geometry; - geom->setStateSet(dstate); - - osg::Vec3Array* coords = new osg::Vec3Array(); - osg::Vec2Array* tcoords = new osg::Vec2Array(); - - int i; - float angle = -Theta/2.0f; - for(i=0; - ipush_back(osg::Vec3(sinf(angle)*radius,cosf(angle)*radius,height*0.5f)); // top - coords->push_back(osg::Vec3(sinf(angle)*radius,cosf(angle)*radius,-height*0.5f)); // bottom. - - tcoords->push_back(osg::Vec2(angle/ThetaZero+0.5f,1.0f)); // top - tcoords->push_back(osg::Vec2(angle/ThetaZero+0.5f,0.0f)); // bottom. - - } - - osg::Vec4Array* colors = new osg::Vec4Array(); - colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); - - osg::DrawArrays* elements = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,coords->size()); - - - - geom->setVertexArray(coords); - geom->setTexCoordArray(0,tcoords); - geom->setColorArray(colors); - geom->setColorBinding(osg::Geometry::BIND_OVERALL); - - geom->addPrimitiveSet(elements); - - // set up the geode. - osg::Geode* geode = new osg::Geode; - geode->addDrawable(geom); - - return geode; - -} - -// create a switch containing a set of child each containing a -// stereo image pair. -osg::Switch* createScene(const FileList& fileList, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length) -{ - osg::Switch* sw = new osg::Switch; - - // load the images. - for(unsigned int i=0;i+1 imageLeft = osgDB::readImageFile(fileList[i]); - osg::ref_ptr imageRight = osgDB::readImageFile(fileList[i+1]); - if (imageLeft.valid() && imageRight.valid()) - { - float average_s = (imageLeft->s()+imageRight->s())*0.5f; - float average_t = (imageLeft->t()+imageRight->t())*0.5f; - - osg::Geode* geodeLeft = createSectorForImage(imageLeft.get(),texmatLeft,average_s,average_t, radius, height, length); - geodeLeft->setNodeMask(0x01); - - osg::Geode* geodeRight = createSectorForImage(imageRight.get(),texmatRight,average_s,average_t, radius, height, length); - geodeRight->setNodeMask(0x02); - - osg::ref_ptr imageGroup = new osg::Group; - - imageGroup->addChild(geodeLeft); - imageGroup->addChild(geodeRight); - - sw->addChild(imageGroup.get()); - } - else - { - std::cout << "Warning: Unable to load both image files, '"<getNumChildren()>0) - { - // select first child. - sw->setSingleChildOn(0); - } - - return sw; -} int main( int argc, char **argv ) { @@ -403,6 +461,7 @@ int main( int argc, char **argv ) 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("--disk","Keep images on disk"); arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer."); arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer."); @@ -430,6 +489,9 @@ int main( int argc, char **argv ) float offsetY=0.0f; while (arguments.read("-y",offsetY)) {} + bool onDisk=false; + while (arguments.read("--disk")) { onDisk=true;} + // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) { @@ -487,8 +549,9 @@ int main( int argc, char **argv ) osg::TexMat* texmatRight = new osg::TexMat; // creat the scene from the file list. - osg::ref_ptr rootNode = createScene(fileList,texmatLeft,texmatRight,radius,height,length); - + osg::ref_ptr rootNode; + if (!onDisk) rootNode = createScene(fileList,texmatLeft,texmatRight,radius,height,length); + else rootNode=new osg::Switch(); //osgDB::writeNodeFile(*rootNode,"test.osg"); @@ -521,7 +584,8 @@ int main( int argc, char **argv ) viewer.setFusionDistance(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE,radius); // set up the SlideEventHandler. - seh->set(rootNode.get(),offsetX,offsetY,texmatLeft,texmatRight,timeDelayBetweenSlides,autoSteppingActive); + if (onDisk) seh->set(fileList,rootNode.get(),offsetX,offsetY,texmatLeft,texmatRight,radius,height,length,timeDelayBetweenSlides,autoSteppingActive); + else seh->set(rootNode.get(),offsetX,offsetY,texmatLeft,texmatRight,timeDelayBetweenSlides,autoSteppingActive); 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));