Added support for openArchive into osgDB
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#define OSGDB_ARCHIVE 1
|
||||
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
@@ -23,8 +24,6 @@ namespace osgDB {
|
||||
|
||||
|
||||
/** Base class for implementing database Archives. */
|
||||
|
||||
|
||||
class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
{
|
||||
public:
|
||||
@@ -37,15 +36,8 @@ class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
|
||||
virtual bool acceptsExtension(const std::string& /*extension*/) { return true; }
|
||||
|
||||
enum Status
|
||||
{
|
||||
READ,
|
||||
WRITE,
|
||||
CREATE
|
||||
};
|
||||
|
||||
/** open the archive.*/
|
||||
virtual bool open(const std::string& filename, Status status, unsigned int indexBlockSizeHint=4096);
|
||||
virtual bool open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSizeHint=4096);
|
||||
|
||||
/** close the archive.*/
|
||||
virtual void close();
|
||||
@@ -98,9 +90,9 @@ class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
|
||||
void write(std::ostream& out);
|
||||
|
||||
inline bool spaceAvailable(pos_type position, size_type size, const std::string& filename) const
|
||||
inline bool spaceAvailable(pos_type, size_type, const std::string& filename) const
|
||||
{
|
||||
unsigned requiredSize = sizeof(position)+sizeof(unsigned int)+filename.size();
|
||||
unsigned requiredSize = sizeof(pos_type)+sizeof(unsigned int)+filename.size();
|
||||
return (_offsetOfNextAvailableSpace + requiredSize)<_blockSize;
|
||||
}
|
||||
|
||||
@@ -132,7 +124,7 @@ class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
|
||||
static float s_currentSupportedVersion;
|
||||
float _version;
|
||||
Status _status;
|
||||
ArchiveStatus _status;
|
||||
std::ifstream _input;
|
||||
std::fstream _output;
|
||||
|
||||
@@ -142,6 +134,12 @@ class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
|
||||
};
|
||||
|
||||
/** Open an archive for reading or writing.*/
|
||||
Archive* openArchive(const std::string& filename, Archive::ArchiveStatus status, unsigned int indexBlockSizeHint=4096);
|
||||
|
||||
/** Open an archive for reading or writing.*/
|
||||
osgDB::Archive* osgDB::openArchive(const std::string& filename, Archive::ArchiveStatus status, unsigned int indexBlockSizeHint,Registry::CacheHintOptions useObjectCache);
|
||||
|
||||
}
|
||||
|
||||
#endif // OSGDB_ARCHIVE
|
||||
|
||||
@@ -21,18 +21,23 @@
|
||||
|
||||
#include <osgDB/Export>
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace osgDB {
|
||||
|
||||
class Archive;
|
||||
|
||||
/** pure virtual base class for reading and writing of non native formats. */
|
||||
class OSGDB_EXPORT ReaderWriter : public osg::Referenced
|
||||
class OSGDB_EXPORT ReaderWriter : public osg::Object
|
||||
{
|
||||
public:
|
||||
virtual ~ReaderWriter(); // {}
|
||||
virtual const char* className() const = 0;
|
||||
|
||||
|
||||
ReaderWriter() {}
|
||||
ReaderWriter(const ReaderWriter& rw,const osg::CopyOp copyop=osg::CopyOp::SHALLOW_COPY):Object(rw,copyop) {}
|
||||
|
||||
virtual ~ReaderWriter();
|
||||
|
||||
META_Object(osgDB,ReaderWriter);
|
||||
|
||||
virtual bool acceptsExtension(const std::string& /*extension*/) { return false; }
|
||||
|
||||
/** Options base class used for passing options into plugins to control their operation.*/
|
||||
@@ -85,20 +90,23 @@ class OSGDB_EXPORT ReaderWriter : public osg::Referenced
|
||||
ReadResult(const ReadResult& rr):_status(rr._status),_message(rr._message),_object(rr._object) {}
|
||||
ReadResult& operator = (const ReadResult& rr) { if (this==&rr) return *this; _status=rr._status; _message=rr._message;_object=rr._object; return *this; }
|
||||
|
||||
osg::Object* getObject() { return _object.get(); }
|
||||
osg::Image* getImage() { return dynamic_cast<osg::Image*>(_object.get()); }
|
||||
osg::HeightField* getHeightField() { return dynamic_cast<osg::HeightField*>(_object.get()); }
|
||||
osg::Node* getNode() { return dynamic_cast<osg::Node*>(_object.get()); }
|
||||
osg::Object* getObject();
|
||||
osg::Image* getImage();
|
||||
osg::HeightField* getHeightField();
|
||||
osg::Node* getNode();
|
||||
osgDB::Archive* getArchive();
|
||||
|
||||
bool validObject() { return _object.valid(); }
|
||||
bool validImage() { return getImage()!=0; }
|
||||
bool validHeightField() { return getHeightField()!=0; }
|
||||
bool validNode() { return getNode()!=0; }
|
||||
bool validArchive() { return getArchive()!=0; }
|
||||
|
||||
osg::Object* takeObject() { osg::Object* obj = _object.get(); if (obj) { obj->ref(); _object=NULL; obj->unref_nodelete(); } return obj; }
|
||||
osg::Image* takeImage() { osg::Image* image=dynamic_cast<osg::Image*>(_object.get()); if (image) { image->ref(); _object=NULL; image->unref_nodelete(); } return image; }
|
||||
osg::HeightField* takeHeightField() { osg::HeightField* hf=dynamic_cast<osg::HeightField*>(_object.get()); if (hf) { hf->ref(); _object=NULL; hf->unref_nodelete(); } return hf; }
|
||||
osg::Node* takeNode() { osg::Node* node=dynamic_cast<osg::Node*>(_object.get()); if (node) { node->ref(); _object=NULL; node->unref_nodelete(); } return node; }
|
||||
osg::Object* takeObject();
|
||||
osg::Image* takeImage();
|
||||
osg::HeightField* takeHeightField();
|
||||
osg::Node* takeNode();
|
||||
osgDB::Archive* takeArchive();
|
||||
|
||||
const std::string& message() const { return _message; }
|
||||
|
||||
@@ -146,6 +154,15 @@ class OSGDB_EXPORT ReaderWriter : public osg::Referenced
|
||||
std::string _message;
|
||||
};
|
||||
|
||||
enum ArchiveStatus
|
||||
{
|
||||
READ,
|
||||
WRITE,
|
||||
CREATE
|
||||
};
|
||||
|
||||
virtual ReadResult openArchive(const std::string& /*fileName*/,ArchiveStatus, unsigned int =4096, const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }
|
||||
|
||||
virtual ReadResult readObject(const std::string& /*fileName*/,const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }
|
||||
virtual ReadResult readImage(const std::string& /*fileName*/,const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }
|
||||
virtual ReadResult readHeightField(const std::string& /*fileName*/,const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }
|
||||
|
||||
@@ -81,14 +81,18 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
|
||||
/// cache heightfield loaded via readHeightField(filename)
|
||||
CACHE_HEIGHTFIELDS = 4,
|
||||
|
||||
/// cache heightfield loaded via readHeightField(filename)
|
||||
CACHE_ARCHIVES = 8,
|
||||
|
||||
/// cache objects loaded via readObject(filename)
|
||||
CACHE_OBJECTS = 8,
|
||||
CACHE_OBJECTS = 16,
|
||||
|
||||
/// cache on all read*(filename) calls
|
||||
CACHE_ALL = CACHE_NODES |
|
||||
CACHE_IMAGES |
|
||||
CACHE_HEIGHTFIELDS |
|
||||
CACHE_ARCHIVES |
|
||||
CACHE_OBJECTS
|
||||
};
|
||||
|
||||
@@ -147,6 +151,11 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ReaderWriter::ReadResult openArchive(const std::string& filename,ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, CacheHintOptions useObjectCache)
|
||||
{
|
||||
return osgDB::Registry::instance()->openArchiveImplementation(filename, status, indexBlockSizeHint, useObjectCache);
|
||||
}
|
||||
|
||||
virtual ReaderWriter::ReadResult readObject(const std::string& filename, CacheHintOptions options)
|
||||
{
|
||||
return osgDB::Registry::instance()->readObjectImplementation(filename,options);
|
||||
@@ -181,6 +190,13 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
const ReadFileCallback* getReadFileCallback() const { return _readFileCallback.get(); }
|
||||
|
||||
|
||||
ReaderWriter::ReadResult openArchive(const std::string& fileName,ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, CacheHintOptions useObjectCache)
|
||||
{
|
||||
if (_readFileCallback.valid()) return _readFileCallback->openArchive(fileName, status, indexBlockSizeHint, useObjectCache);
|
||||
else return openArchiveImplementation(fileName, status, indexBlockSizeHint, useObjectCache);
|
||||
}
|
||||
ReaderWriter::ReadResult openArchiveImplementation(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, CacheHintOptions useObjectCache);
|
||||
|
||||
ReaderWriter::ReadResult readObject(const std::string& fileName,CacheHintOptions useObjectCache)
|
||||
{
|
||||
if (_readFileCallback.valid()) return _readFileCallback->readObject(fileName,useObjectCache);
|
||||
@@ -210,6 +226,11 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
ReaderWriter::ReadResult readNodeImplementation(const std::string& fileName,CacheHintOptions useObjectCache);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class WriteFileCallback : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
@@ -277,6 +298,7 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
ReaderWriter::WriteResult writeNodeImplementation(const osg::Node& node, const std::string& fileName);
|
||||
|
||||
|
||||
|
||||
void setCreateNodeFromImage(bool flag) { _createNodeFromImage = flag; }
|
||||
bool getCreateNodeFromImage() const { return _createNodeFromImage; }
|
||||
|
||||
@@ -401,6 +423,7 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
|
||||
void eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper);
|
||||
|
||||
ReaderWriter::ReadResult openArchive(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint);
|
||||
ReaderWriter::ReadResult readObject(const std::string& fileName);
|
||||
ReaderWriter::ReadResult readImage(const std::string& fileName);
|
||||
ReaderWriter::ReadResult readHeightField(const std::string& fileName);
|
||||
|
||||
@@ -21,6 +21,17 @@ using namespace osgDB;
|
||||
|
||||
float Archive::s_currentSupportedVersion = 0.0;
|
||||
|
||||
osgDB::Archive* osgDB::openArchive(const std::string& filename, Archive::ArchiveStatus status, unsigned int indexBlockSizeHint)
|
||||
{
|
||||
return openArchive(filename, status, indexBlockSizeHint, Registry::instance()->getUseObjectCacheHint());
|
||||
}
|
||||
|
||||
osgDB::Archive* osgDB::openArchive(const std::string& filename, Archive::ArchiveStatus status, unsigned int indexBlockSizeHint,Registry::CacheHintOptions useObjectCache)
|
||||
{
|
||||
ReaderWriter::ReadResult result = osgDB::Registry::instance()->openArchive(filename, status, indexBlockSizeHint, useObjectCache);
|
||||
return result.takeArchive();
|
||||
}
|
||||
|
||||
Archive::IndexBlock::IndexBlock(unsigned int blockSize):
|
||||
_requiresWrite(false),
|
||||
_filePosition(0),
|
||||
@@ -185,7 +196,7 @@ Archive::~Archive()
|
||||
}
|
||||
#include <sys/stat.h>
|
||||
|
||||
bool Archive::open(const std::string& filename, Status status, unsigned int indexBlockSize)
|
||||
bool Archive::open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSize)
|
||||
{
|
||||
if (status==READ)
|
||||
{
|
||||
@@ -295,6 +306,7 @@ bool Archive::open(const std::string& filename, Status status, unsigned int inde
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Archive::open("<<filename<<") is a strange place!!."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,22 @@
|
||||
*/
|
||||
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osgDB/Archive>
|
||||
|
||||
using namespace osgDB;
|
||||
|
||||
osg::Object* ReaderWriter::ReadResult::getObject() { return _object.get(); }
|
||||
osg::Image* ReaderWriter::ReadResult::getImage() { return dynamic_cast<osg::Image*>(_object.get()); }
|
||||
osg::HeightField* ReaderWriter::ReadResult::getHeightField() { return dynamic_cast<osg::HeightField*>(_object.get()); }
|
||||
osg::Node* ReaderWriter::ReadResult::getNode() { return dynamic_cast<osg::Node*>(_object.get()); }
|
||||
osgDB::Archive* ReaderWriter::ReadResult::getArchive() { return dynamic_cast<osgDB::Archive*>(_object.get()); }
|
||||
|
||||
osg::Object* ReaderWriter::ReadResult::takeObject() { osg::Object* obj = _object.get(); if (obj) { obj->ref(); _object=NULL; obj->unref_nodelete(); } return obj; }
|
||||
osg::Image* ReaderWriter::ReadResult::takeImage() { osg::Image* image=dynamic_cast<osg::Image*>(_object.get()); if (image) { image->ref(); _object=NULL; image->unref_nodelete(); } return image; }
|
||||
osg::HeightField* ReaderWriter::ReadResult::takeHeightField() { osg::HeightField* hf=dynamic_cast<osg::HeightField*>(_object.get()); if (hf) { hf->ref(); _object=NULL; hf->unref_nodelete(); } return hf; }
|
||||
osg::Node* ReaderWriter::ReadResult::takeNode() { osg::Node* node=dynamic_cast<osg::Node*>(_object.get()); if (node) { node->ref(); _object=NULL; node->unref_nodelete(); } return node; }
|
||||
osgDB::Archive* ReaderWriter::ReadResult::takeArchive() { osgDB::Archive* archive=dynamic_cast<osgDB::Archive*>(_object.get()); if (archive) { archive->ref(); _object=NULL; archive->unref_nodelete(); } return archive; }
|
||||
|
||||
ReaderWriter::~ReaderWriter()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/Archive>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1113,6 +1114,162 @@ bool Registry::writeObject(const osg::Object& obj,Output& fw)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// read object from specified file.
|
||||
//
|
||||
ReaderWriter::ReadResult Registry::openArchive(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint)
|
||||
{
|
||||
if (containsServerAddress(fileName))
|
||||
{
|
||||
std::string serverName = getServerAddress(fileName);
|
||||
std::string serverFile = getServerFileName(fileName);
|
||||
osg::notify(osg::INFO)<<"Contains sever address : "<<serverName<<std::endl;
|
||||
osg::notify(osg::INFO)<<" file name on server : "<<serverFile<<std::endl;
|
||||
|
||||
if (serverName.empty())
|
||||
{
|
||||
return ReaderWriter::ReadResult("Warning: Server address invalid.");
|
||||
}
|
||||
|
||||
if (serverFile.empty())
|
||||
{
|
||||
return ReaderWriter::ReadResult("Warning: Server file name invalid.");
|
||||
}
|
||||
|
||||
ReaderWriter* rw = getReaderWriterForExtension("net");
|
||||
if (rw)
|
||||
{
|
||||
return rw->openArchive(serverName+":"+serverFile, status, indexBlockSizeHint, _options.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReaderWriter::ReadResult("Warning: Could not find the .net plugin to read from server.");
|
||||
}
|
||||
}
|
||||
|
||||
// record the errors reported by readerwriters.
|
||||
typedef std::vector<ReaderWriter::ReadResult> Results;
|
||||
Results results;
|
||||
|
||||
// first attempt to load the file from existing ReaderWriter's
|
||||
AvailableReaderWriterIterator itr(_rwList);
|
||||
for(;itr.valid();++itr)
|
||||
{
|
||||
ReaderWriter::ReadResult rr = itr->openArchive(fileName,status, indexBlockSizeHint, _options.get());
|
||||
if (rr.validArchive()) return rr;
|
||||
else results.push_back(rr);
|
||||
}
|
||||
|
||||
if (!results.empty())
|
||||
{
|
||||
unsigned int num_FILE_NOT_HANDLED = 0;
|
||||
unsigned int num_FILE_NOT_FOUND = 0;
|
||||
unsigned int num_ERROR_IN_READING_FILE = 0;
|
||||
|
||||
for(Results::iterator ritr=results.begin();
|
||||
ritr!=results.end();
|
||||
++ritr)
|
||||
{
|
||||
if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
|
||||
else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
|
||||
else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
|
||||
}
|
||||
|
||||
if (num_FILE_NOT_HANDLED!=results.size())
|
||||
{
|
||||
// we've come across a file not found or error in reading file.
|
||||
if (num_ERROR_IN_READING_FILE)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
else if (num_FILE_NOT_FOUND)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now look for a plug-in to load the file.
|
||||
std::string libraryName = createLibraryNameForFile(fileName);
|
||||
if (loadLibrary(libraryName))
|
||||
{
|
||||
for(;itr.valid();++itr)
|
||||
{
|
||||
ReaderWriter::ReadResult rr = itr->openArchive(fileName,status, indexBlockSizeHint, _options.get());
|
||||
if (rr.validArchive()) return rr;
|
||||
else results.push_back(rr);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.empty())
|
||||
{
|
||||
return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+fileName+"\".");
|
||||
}
|
||||
|
||||
|
||||
return results.front();
|
||||
}
|
||||
|
||||
ReaderWriter::ReadResult Registry::openArchiveImplementation(const std::string& fileName, ReaderWriter::ArchiveStatus status, unsigned int indexBlockSizeHint, CacheHintOptions useObjectCache)
|
||||
{
|
||||
std::string file(fileName);
|
||||
|
||||
if (useObjectCache & CACHE_OBJECTS)
|
||||
{
|
||||
// search for entry in the object cache.
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
ObjectCache::iterator oitr=_objectCache.find(file);
|
||||
if (oitr!=_objectCache.end())
|
||||
{
|
||||
notify(INFO)<<"returning cached instanced of "<<file<<std::endl;
|
||||
osgDB::Archive* archive = dynamic_cast<osgDB::Archive*>(oitr->second.first.get());
|
||||
if (archive) return ReaderWriter::ReadResult(archive, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
|
||||
else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
|
||||
}
|
||||
}
|
||||
|
||||
PushAndPopDataPath tmpfile(getFilePath(file));
|
||||
|
||||
ReaderWriter::ReadResult rr = openArchive(file, status, indexBlockSizeHint);
|
||||
if (rr.validObject())
|
||||
{
|
||||
// update cache with new entry.
|
||||
notify(INFO)<<"Adding to cache object "<<file<<std::endl;
|
||||
addEntryToObjectCache(file,rr.getObject());
|
||||
}
|
||||
|
||||
return rr;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ObjectCache tmpObjectCache;
|
||||
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
tmpObjectCache.swap(_objectCache);
|
||||
}
|
||||
|
||||
PushAndPopDataPath tmpfile(getFilePath(file));
|
||||
|
||||
ReaderWriter::ReadResult rr = openArchive(file, status, indexBlockSizeHint);
|
||||
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
tmpObjectCache.swap(_objectCache);
|
||||
}
|
||||
|
||||
return rr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// read object from specified file.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user