From 42527fe8594b68668beaf27e43d1111fa46375ae Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 12 May 2010 20:02:31 +0000 Subject: [PATCH] From Wang Rui, "I'd like to submit my inbuilt schema data support of the OutputStream/InputStream implementations, which was just finished last weekend with a few tests on Windows and Ubuntu. Hope it could work and get more feedbacks soon. I've added a new option "SchemaData" to the osg2 plugin. Developers may test the new feature with the command line: # osgconv cow.osg cow.osgb -O SchemaData It will record all serializer properties used in the scene graph, at the beginning of the generated file. And when osgviewer and user applications is going to read the osgb file, the inbuilt data will be automatically read and applied first, to keep backwards compatibility partly. This will not affect osgb files generated with older versions. " --- include/osgDB/InputStream | 1 + include/osgDB/OutputStream | 2 + src/osgDB/InputStream.cpp | 45 +++++----- src/osgDB/OutputStream.cpp | 104 ++++++++++++++++++++---- src/osgPlugins/osg/ReaderWriterOSG2.cpp | 3 +- 5 files changed, 117 insertions(+), 38 deletions(-) diff --git a/include/osgDB/InputStream b/include/osgDB/InputStream index d17f3c7b3..d84d294db 100644 --- a/include/osgDB/InputStream +++ b/include/osgDB/InputStream @@ -161,6 +161,7 @@ protected: int _byteSwap; bool _useFloatMatrix; + bool _useSchemaData; bool _forceReadingImage; std::vector _fields; osg::ref_ptr _in; diff --git a/include/osgDB/OutputStream b/include/osgDB/OutputStream index 4519bb569..d18506c6c 100644 --- a/include/osgDB/OutputStream +++ b/include/osgDB/OutputStream @@ -168,6 +168,8 @@ protected: ObjectMap _objectMap; WriteImageHint _writeImageHint; + bool _useSchemaData; + std::map _inbuiltSchemaMap; std::vector _fields; std::string _schemaName; std::string _compressorName; diff --git a/src/osgDB/InputStream.cpp b/src/osgDB/InputStream.cpp index 1558243b3..6ab942727 100644 --- a/src/osgDB/InputStream.cpp +++ b/src/osgDB/InputStream.cpp @@ -24,7 +24,7 @@ using namespace osgDB; static std::string s_lastSchema; InputStream::InputStream( const osgDB::Options* options ) -: _byteSwap(0), _useFloatMatrix(false), _forceReadingImage(false) +: _byteSwap(0), _useFloatMatrix(true), _useSchemaData(false), _forceReadingImage(false) { if ( !options ) return; _options = options; @@ -624,9 +624,9 @@ InputStream::ReadType InputStream::start( InputIterator* inIterator ) *this >> typeValue >> version; type = static_cast(typeValue); - unsigned int matrixValueType; *this >> matrixValueType; - if ( matrixValueType==0 ) _useFloatMatrix = true; - else _useFloatMatrix = false; + unsigned int attributes; *this >> attributes; + if ( attributes&0x1 ) _useFloatMatrix = false; + if ( attributes&0x2 ) _useSchemaData = true; } if ( !isBinary() ) { @@ -655,29 +655,36 @@ void InputStream::decompress() { if ( !isBinary() ) return; _fields.clear(); - _fields.push_back( "Decompression" ); std::string compressorName; *this >> compressorName; - if ( compressorName=="0" ) + if ( compressorName!="0" ) { + std::string data; + _fields.push_back( "Decompression" ); + + BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName); + if ( !compressor ) + { + osg::notify(osg::WARN) << "InputStream::decompress(): No such compressor " + << compressorName << std::endl; + } + + if ( !compressor->decompress(*(_in->getStream()), data) ) + throwException( "InputStream: Failed to decompress stream." ); + if ( getException() ) return; + + _in->setStream( new std::stringstream(data) ); _fields.pop_back(); - return; } - BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName); - if ( !compressor ) + if ( _useSchemaData ) { - osg::notify(osg::WARN) << "InputStream::decompress(): No such compressor " - << compressorName << std::endl; + _fields.push_back( "SchemaData" ); + std::string schemaSource; *this >> schemaSource; + std::istringstream iss( schemaSource ); + readSchema( iss ); + _fields.pop_back(); } - - std::string data; - if ( !compressor->decompress(*(_in->getStream()), data) ) - throwException( "InputStream: Failed to decompress stream." ); - if ( getException() ) return; - - _in->setStream( new std::stringstream(data) ); - _fields.pop_back(); } // PROTECTED METHODS diff --git a/src/osgDB/OutputStream.cpp b/src/osgDB/OutputStream.cpp index 14d585de3..40ab99930 100644 --- a/src/osgDB/OutputStream.cpp +++ b/src/osgDB/OutputStream.cpp @@ -22,7 +22,7 @@ using namespace osgDB; OutputStream::OutputStream( const osgDB::Options* options ) -: _writeImageHint(WRITE_USE_IMAGE_HINT) +: _writeImageHint(WRITE_USE_IMAGE_HINT), _useSchemaData(false) { if ( !options ) return; _options = options; @@ -36,6 +36,10 @@ OutputStream::OutputStream( const osgDB::Options* options ) { // Omit this } + else if ( option=="SchemaData" ) + { + _useSchemaData = true; + } else { StringList keyAndValues; @@ -422,13 +426,32 @@ void OutputStream::writeObject( const osg::Object* obj ) const StringList& associates = wrapper->getAssociates(); for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) { - ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr); + const std::string& assocName = *itr; + ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); if ( !assocWrapper ) { osg::notify(osg::WARN) << "OutputStream::writeObject(): Unsupported associated class " - << *itr << std::endl; + << assocName << std::endl; continue; } + else if ( _useSchemaData ) + { + if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() ) + { + StringList properties; + assocWrapper->writeSchema( properties ); + if ( properties.size()>0 ) + { + std::string propertiesString; + for ( StringList::iterator sitr=properties.begin(); sitr!=properties.end(); ++sitr ) + { + propertiesString += *sitr; + propertiesString += ' '; + } + _inbuiltSchemaMap[assocName] = propertiesString; + } + } + } _fields.push_back( assocWrapper->getName() ); assocWrapper->write( *this, *obj ); @@ -455,8 +478,16 @@ void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType t { *this << (unsigned int)type << (unsigned int)PLUGIN_VERSION; - if ( sizeof(osg::Matrix::value_type)==FLOAT_SIZE ) *this << (unsigned int)0; - else *this << (unsigned int)1; // Record matrix value type of current built OSG + bool useCompressSource = false; + unsigned int attributes = 0; + if ( sizeof(osg::Matrix::value_type)!=FLOAT_SIZE ) + attributes |= 0x1; // Record matrix value type of current built OSG + if ( _useSchemaData ) + { + attributes |= 0x2; // Record if we use inbuilt schema data or not + useCompressSource = true; + } + *this << attributes; if ( !_compressorName.empty() ) { @@ -465,16 +496,22 @@ void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType t { osg::notify(osg::WARN) << "OutputStream::start(): No such compressor " << _compressorName << std::endl; + _compressorName.clear(); } else { - *this << _compressorName; - _out->flush(); - _out->setStream( &_compressSource ); - return; + useCompressSource = true; } } - *this << std::string("0"); + if ( !_compressorName.empty() ) *this << _compressorName; + else *this << std::string("0"); // No compressor + + // Compressors and inbuilt schema use a new stream, which will be merged with the original one at the end. + if ( useCompressSource ) + { + _out->flush(); + _out->setStream( &_compressSource ); + } } else { @@ -498,20 +535,51 @@ void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType t void OutputStream::compress( std::ostream* ostream ) { - if ( _compressorName.empty() || !isBinary() ) return; _fields.clear(); - _fields.push_back( "Compression" ); + if ( !isBinary() ) return; - BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName); - if ( !compressor || !ostream ) + std::stringstream schemaSource; + if ( _useSchemaData ) { + _fields.push_back( "SchemaData" ); + + std::string schemaData; + for ( std::map::iterator itr=_inbuiltSchemaMap.begin(); + itr!=_inbuiltSchemaMap.end(); ++itr ) + { + schemaData += itr->first + '='; + schemaData += itr->second; + schemaData += '\n'; + } + + int size = schemaData.size(); + schemaSource.write( (char*)&size, INT_SIZE ); + schemaSource.write( schemaData.c_str(), size ); + + _inbuiltSchemaMap.clear(); _fields.pop_back(); - return; } - if ( !compressor->compress(*ostream, _compressSource.str()) ) - throwException( "OutputStream: Failed to compress stream." ); - _fields.pop_back(); + if ( !_compressorName.empty() ) + { + _fields.push_back( "Compression" ); + BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName); + if ( !compressor || !ostream ) + { + _fields.pop_back(); + return; + } + + if ( !compressor->compress(*ostream, schemaSource.str() + _compressSource.str()) ) + throwException( "OutputStream: Failed to compress stream." ); + if ( getException() ) return; + _fields.pop_back(); + } + else if ( _useSchemaData ) + { + std::string str = schemaSource.str() + _compressSource.str(); + ostream->write( str.c_str(), str.size() ); + } } void OutputStream::writeSchema( std::ostream& fout ) diff --git a/src/osgPlugins/osg/ReaderWriterOSG2.cpp b/src/osgPlugins/osg/ReaderWriterOSG2.cpp index 2544eeaef..e0c0a9aff 100644 --- a/src/osgPlugins/osg/ReaderWriterOSG2.cpp +++ b/src/osgPlugins/osg/ReaderWriterOSG2.cpp @@ -103,7 +103,8 @@ public: supportsOption( "Ascii", "Import/Export option: Force reading/writing ascii file" ); supportsOption( "XML", "Import/Export option: Force reading/writing XML file" ); supportsOption( "ForceReadingImage", "Import option: Load an empty image instead if required file missed" ); - supportsOption( "SchemaFile=", "Import/Export option: Use/Record a ascii schema file" ); + supportsOption( "SchemaData", "Export option: Record inbuilt schema data into a binary file" ); + supportsOption( "SchemaFile=", "Import/Export option: Use/Record an ascii schema file" ); supportsOption( "Compressor=", "Export option: Use an inbuilt or user-defined compressor" ); supportsOption( "WriteImageHint=", "Export option: Hint of writing image to stream: " " writes Image::data() directly; "