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."
This commit is contained in:
Robert Osfield 2007-08-13 10:31:33 +00:00
parent 21f65054a0
commit d8d0f65e81

View File

@ -32,6 +32,121 @@
typedef std::vector<std::string> 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;
i<numSegments;
++i, angle+=dTheta)
{
coords->push_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<osg::Image> imageLeft = osgDB::readImageFile(image1);
osg::ref_ptr<osg::Image> 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, '"<<image1<<"' & '"<<image2<<"', required for stereo imaging."<<std::endl;
return 0;
}
}
// create a switch containing a set of child each containing a
// stereo image pair.
osg::Switch* createScene(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<fileList.size();i+=2)
{
osg::Group * imageGroup = loadImages(fileList[i],fileList[i+1],texmatLeft,texmatRight, radius, height, length);
if (imageGroup) sw->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<osg::Switch> _switch;
osg::ref_ptr<osg::TexMat> _texmatLeft;
osg::ref_ptr<osg::TexMat> _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<osg::Group> 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,23 +385,39 @@ void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv)
void SlideEventHandler::nextSlide()
{
if (_switch->getNumChildren()==0) return;
++_activeSlide;
if (_fileList.size()>0) {
if (_activeSlide>= _fileList.size()/2 ) _activeSlide = 0;
osg::ref_ptr<osg::Group> 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 (_fileList.size()>0) {
if (_activeSlide==0) _activeSlide = _fileList.size()/2-1;
else --_activeSlide;
osg::ref_ptr<osg::Group> 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);
}
}
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;
i<numSegments;
++i, angle+=dTheta)
{
coords->push_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<fileList.size();i+=2)
{
osg::ref_ptr<osg::Image> imageLeft = osgDB::readImageFile(fileList[i]);
osg::ref_ptr<osg::Image> 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<osg::Group> imageGroup = new osg::Group;
imageGroup->addChild(geodeLeft);
imageGroup->addChild(geodeRight);
sw->addChild(imageGroup.get());
}
else
{
std::cout << "Warning: Unable to load both image files, '"<<fileList[i]<<"' & '"<<fileList[i+1]<<"', required for stereo imaging."<<std::endl;
}
}
if (sw->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 <float>","Horizontal offset of left and right images.");
arguments.getApplicationUsage()->addCommandLineOption("-y <float>","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<osg::Switch> rootNode = createScene(fileList,texmatLeft,texmatRight,radius,height,length);
osg::ref_ptr<osg::Switch> 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));