#include <osgViewer/Viewer>
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <iostream>
template<typename Elem, typename Tr = std::char_traits<Elem>>
class ProgressingStreamBuf : public std::basic_filebuf<Elem, Tr>
{
public:
typedef std::basic_filebuf<Elem, Tr> BaseType;
ProgressingStreamBuf(const std::string& filename)
:BaseType(), _count(0), _readSize(0)
{
if (open(filename.c_str(), std::ios_base::in | std::ios_base::binary))
{
pubseekoff(0, std::ios_base::beg, std::ios_base::in);
}
}
protected:
virtual int_type uflow()
{
int_type value = BaseType::uflow();
_count++;
_readSize += egptr() - gptr();
if (0 == (_count % 10))
{
std::cout << _readSize;
}
else
{
std::cout << ".";
}
return value;
}
int _count;
int _readSize;
};
class ProgressingReadCallback : public osgDB::Registry::ReadFileCallback
{
public:
typedef ProgressingStreamBuf<char> ProgressingStringBuf;
typedef osgDB::ReaderWriter::ReadResult ReadResult;
ProgressingReadCallback() {}
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& file, const osgDB::Options* option)
{
std::string ext = osgDB::getLowerCaseFileExtension(file);
osgDB::ReaderWriter::ReadResult rr;
osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
if (rw)
{
std::string fileName = osgDB::findDataFile(file, option);
if (fileName.empty()) return ReadResult::ReadResult::FILE_NOT_FOUND;
ProgressingStringBuf* ps = new ProgressingStringBuf(fileName);
if (!ps->is_open())
{
return ReadResult::ERROR_IN_READING_FILE;
}
std::istream s(ps);
rr = rw->readNode(s, option);
delete ps;
}
else
{
rr = osgDB::Registry::instance()->readNodeImplementation(file, option);
}
return rr;
}
};
int main(int argc, char**argv)
{
osg::ArgumentParser arguments(&argc, argv);
osgDB::Registry::instance()->setReadFileCallback(new ProgressingReadCallback);
osg::Node* model = osgDB::readNodeFiles(arguments);
if (!model) model = osgDB::readNodeFile("cow.osg");
osgViewer::Viewer viewer;
viewer.setSceneData(model);
return viewer.run();
}
注:
原书第74行是:
rr = rw->readNode(std::istream(ps), option);
但这样编译通不过,所以就改为了上面的第73、74行。关于std::basic_filebuf用法,参见:
运行结果如下: