From d8d0f65e817c665c461c16fdbf0526b59dcf29b6 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 13 Aug 2007 10:31:33 +0000 Subject: [PATCH] From Luc Frauciel, "I've done 2 main modifications : 1) added texture->setResizeNonPowerOfTwoHint(false); when loading an image. It speeds up by 10 the loading of large images. 2) added a --disk option : only a filelist is read, images are only loaded when needed. It allows to handle very large set of very large images that would not fit in memory. Nothing change when the option is not set." --- examples/osgstereoimage/osgstereoimage.cpp | 298 +++++++++++++-------- 1 file changed, 181 insertions(+), 117 deletions(-) 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));