From Wang Rui, "The file attached includes two new features for the serialization IO functionality. First, custom serializer version control should work now, just by defining a new REGISTER_CUSTOM_OBJECT_WRAPPER macro. For example:

// A custom class
namespace CustomDomain {

class MyGroup : public osg::Group
{
public:
    META_Node( CustomDomain, MyGroup );

    void setMyName( const std::string& n );
    const std::string& getMyName() const;

    void setMyID( int id );
    int getMyID() const;

    ...
};

}

// The serialization wrapper using a custom domain name
REGISTER_CUSTOM_OBJECT_WRAPPER( MyDomain,
                                CustomDomain_MyGroup,
                                new CustomDomain::MyGroup,
                                CustomDomain::MyGroup,
                                "osg::Object osg::Node osg::Group CustomDomain::MyGroup" )
{
    ADD_STRING_SERIALIZER( MyName, std::string() );
    {
        UPDATE_TO_VERSION_SCOPED( 1 );  // Updated for a new domain version
        ADD_INT_SERIALIZER( MyID, 0 );
    }
}

Save the class instance as follows:
osgDB::writeNodeFile( *myGroup, "serializer_test.osgt", new osgDB::Options("CustomDomains=MyDomain:1") );

The output file will include the domain version definition and all the class data, and can be read back. We can also force setting the domain version by the CustomDomains option while reading the saved files. If we save the class instance without any options, MyID will be ignored because the default domain version is 0.

This may help third-party libraries like osgEarth to maintain their own serializers without regarding to the OSG soversion changes.

Another feature added is a more robust binary format, which in fact adds a size-offset at each block's beginning. When there are problems or unsupported data types while reading, we can now directly jump to the block end indicated by the offset value. So a .osgb file will automatically ignore bad data and read remains as normal (at present it will fail at all). This feature will not break the backward compatibility, and can be disabled by setting "RobustBinaryFormat=false" while writing out.

Hope these changes can work smoothly with present and future community projects. Maybe we should also consider have an osgserializer example to test and demonstrate all things we can do now."
This commit is contained in:
Robert Osfield
2013-06-24 08:48:55 +00:00
parent b3f0479118
commit 4044fd5a74
8 changed files with 245 additions and 18 deletions

View File

@@ -75,8 +75,10 @@ public:
InputStream( const osgDB::Options* options );
virtual ~InputStream();
void setFileVersion( const std::string& d, int v ) { _domainVersionMap[d] = v; }
int getFileVersion( const std::string& d=std::string() ) const;
bool isBinary() const { return _in->isBinary(); }
int getFileVersion() const { return _fileVersion; }
const osgDB::Options* getOptions() const { return _options.get(); }
// Serialization related functions
@@ -184,6 +186,7 @@ protected:
ArrayMap _arrayMap;
IdentifierMap _identifierMap;
std::map<std::string, int> _domainVersionMap;
int _fileVersion;
bool _useSchemaData;
bool _forceReadingImage;

View File

@@ -50,7 +50,9 @@ public:
ObjectWrapper( osg::Object* proto, const std::string& name,
const std::string& associates );
ObjectWrapper( osg::Object* proto, const std::string& domain, const std::string& name,
const std::string& associates );
void setUpdatedVersion( int ver ) { _version = ver; }
int getUpdatedVersion() const { return _version; }
@@ -76,6 +78,7 @@ protected:
virtual ~ObjectWrapper() {}
osg::ref_ptr<osg::Object> _proto;
std::string _domain;
std::string _name;
StringList _associates;
SerializerList _serializers;
@@ -165,6 +168,20 @@ protected:
osg::ref_ptr<ObjectWrapper> _wrapper;
};
class OSGDB_EXPORT RegisterCustomWrapperProxy
{
public:
typedef void (*AddPropFunc)( const char*, ObjectWrapper* );
RegisterCustomWrapperProxy( osg::Object* proto, const std::string& domain, const std::string& name,
const std::string& associates, AddPropFunc func );
virtual ~RegisterCustomWrapperProxy();
protected:
osg::ref_ptr<ObjectWrapper> _wrapper;
};
#define REGISTER_OBJECT_WRAPPER(NAME, PROTO, CLASS, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(osgDB::ObjectWrapper*); \
@@ -181,6 +198,22 @@ protected:
typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(osgDB::ObjectWrapper* wrapper)
#define REGISTER_CUSTOM_OBJECT_WRAPPER(DOMAIN, NAME, PROTO, CLASS, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \
static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \
PROTO, #DOMAIN, #CLASS, ASSOCIATES, &wrapper_propfunc_##NAME); \
typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper)
#define REGISTER_CUSTOM_OBJECT_WRAPPER2(DOMAIN, NAME, PROTO, CLASS, CLASSNAME, ASSOCIATES) \
extern "C" void wrapper_serializer_##NAME(void) {} \
extern void wrapper_propfunc_##NAME(const char*, osgDB::ObjectWrapper*); \
static osgDB::RegisterCustomWrapperProxy wrapper_proxy_##NAME( \
PROTO, #DOMAIN, CLASSNAME, ASSOCIATES, &wrapper_propfunc_##NAME); \
typedef CLASS MyClass; \
void wrapper_propfunc_##NAME(const char* domain, osgDB::ObjectWrapper* wrapper)
class OSGDB_EXPORT RegisterCompressorProxy
{
public:

View File

@@ -76,6 +76,9 @@ public:
OutputStream( const osgDB::Options* options );
virtual ~OutputStream();
void setFileVersion( const std::string& d, int v ) { _domainVersionMap[d] = v; }
int getFileVersion( const std::string& d=std::string() ) const;
bool isBinary() const { return _out->isBinary(); }
const std::string& getSchemaName() const { return _schemaName; }
const osgDB::Options* getOptions() const { return _options.get(); }
@@ -185,8 +188,9 @@ protected:
ArrayMap _arrayMap;
ObjectMap _objectMap;
std::map<std::string, int> _domainVersionMap;
WriteImageHint _writeImageHint;
bool _useSchemaData;
bool _useSchemaData, _useRobustBinaryFormat;
std::map<std::string, std::string> _inbuiltSchemaMap;
std::vector<std::string> _fields;
std::string _schemaName;

View File

@@ -16,13 +16,16 @@ class InputStream;
class OSGDB_EXPORT OutputIterator : public osg::Referenced
{
public:
OutputIterator() : _out(0) {}
OutputIterator() : _out(0), _supportBinaryBrackets(false) {}
virtual ~OutputIterator() {}
void setStream( std::ostream* ostream ) { _out = ostream; }
std::ostream* getStream() { return _out; }
const std::ostream* getStream() const { return _out; }
void setSupportBinaryBrackets( bool b ) { _supportBinaryBrackets = b; }
bool getSupportBinaryBrackets() const { return _supportBinaryBrackets; }
virtual bool isBinary() const = 0;
virtual void writeBool( bool b ) = 0;
@@ -64,12 +67,13 @@ protected:
}
std::ostream* _out;
bool _supportBinaryBrackets;
};
class OSGDB_EXPORT InputIterator : public osg::Referenced
{
public:
InputIterator() : _in(0), _inputStream(0), _byteSwap(0), _failed(false) {}
InputIterator() : _in(0), _inputStream(0), _byteSwap(0), _supportBinaryBrackets(false), _failed(false) {}
virtual ~InputIterator() {}
void setStream( std::istream* istream ) { _in = istream; }
@@ -83,6 +87,9 @@ public:
void setByteSwap(int byteSwap) { _byteSwap = byteSwap; }
int getByteSwap() const { return _byteSwap; }
void setSupportBinaryBrackets( bool b ) { _supportBinaryBrackets = b; }
bool getSupportBinaryBrackets() const { return _supportBinaryBrackets; }
void checkStream() const { if (_in->rdstate()&_in->failbit) _failed = true; }
bool isFailed() const { return _failed; }
@@ -121,6 +128,7 @@ protected:
std::istream* _in;
osgDB::InputStream* _inputStream;
int _byteSwap;
bool _supportBinaryBrackets;
mutable bool _failed;
};