Files
OpenSceneGraph/src/osgPlugins/osg/ReaderWriterOSG2.cpp
Robert Osfield 42527fe859 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.
"
2010-05-12 20:02:31 +00:00

346 lines
13 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
// Written by Wang Rui, (C) 2010
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <osgDB/ObjectWrapper>
#include "AsciiStreamOperator.h"
#include "BinaryStreamOperator.h"
#include "XmlStreamOperator.h"
using namespace osgDB;
#define CATCH_EXCEPTION(s) \
if (s.getException()) return (s.getException()->getError() + " At " + s.getException()->getField());
InputIterator* readInputIterator( std::istream& fin, const Options* options )
{
bool extensionIsAscii = false, extensionIsXML = false;
if ( options )
{
const std::string& optionString = options->getOptionString();
if ( optionString.find("Ascii")!=std::string::npos ) extensionIsAscii = true;
else if ( optionString.find("XML")!=std::string::npos ) extensionIsXML = true;
}
if ( !extensionIsAscii && !extensionIsXML )
{
unsigned int headerLow = 0, headerHigh = 0;
fin.read( (char*)&headerLow, INT_SIZE );
fin.read( (char*)&headerHigh, INT_SIZE );
if ( headerLow==OSG_HEADER_LOW && headerHigh==OSG_HEADER_HIGH )
{
return new BinaryInputIterator(&fin);
}
fin.seekg( 0, std::ios::beg );
}
if ( !extensionIsXML )
{
std::string header; fin >> header;
if ( header=="#Ascii" )
{
return new AsciiInputIterator(&fin);
}
fin.seekg( 0, std::ios::beg );
}
if ( 1 )
{
std::string header; std::getline( fin, header );
if ( !header.compare(0, 5, "<?xml") )
{
return new XmlInputIterator(&fin);
}
fin.seekg( 0, std::ios::beg );
}
return NULL;
}
OutputIterator* writeInputIterator( std::ostream& fout, const Options* options )
{
if ( options && options->getOptionString().find("Ascii")!=std::string::npos )
{
fout << std::string("#Ascii") << ' ';
return new AsciiOutputIterator(&fout);
}
else if ( options && options->getOptionString().find("XML")!=std::string::npos )
{
fout << std::string("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>") << std::endl;
return new XmlOutputIterator(&fout);
}
else
{
unsigned int low = OSG_HEADER_LOW, high = OSG_HEADER_HIGH;
fout.write( (char*)&low, INT_SIZE );
fout.write( (char*)&high, INT_SIZE );
return new BinaryOutputIterator(&fout);
}
}
class ReaderWriterOSG2 : public osgDB::ReaderWriter
{
public:
ReaderWriterOSG2()
{
supportsExtension( "osg2", "OpenSceneGraph extendable format" );
supportsExtension( "osgt", "OpenSceneGraph extendable ascii format" );
supportsExtension( "osgb", "OpenSceneGraph extendable binary format" );
supportsExtension( "osgx", "OpenSceneGraph extendable XML format" );
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( "SchemaData", "Export option: Record inbuilt schema data into a binary file" );
supportsOption( "SchemaFile=<file>", "Import/Export option: Use/Record an ascii schema file" );
supportsOption( "Compressor=<name>", "Export option: Use an inbuilt or user-defined compressor" );
supportsOption( "WriteImageHint=<hint>", "Export option: Hint of writing image to stream: "
"<IncludeData> writes Image::data() directly; "
"<IncludeFile> writes the image file itself to stream; "
"<UseExternal> writes only the filename; "
"<WriteOut> writes Image::data() to disk as external file." );
}
virtual const char* className() const { return "OpenSceneGraph Native Format Reader/Writer"; }
Options* prepareReading( ReadResult& result, std::string& fileName, const Options* options ) const
{
std::string ext = osgDB::getLowerCaseFileExtension( fileName );
if ( !acceptsExtension(ext) )
{
result = ReadResult::FILE_NOT_HANDLED;
return 0;
}
fileName = osgDB::findDataFile( fileName, options );
if ( fileName.empty() )
{
result = ReadResult::FILE_NOT_FOUND;
return 0;
}
osg::ref_ptr<Options> local_opt = options ?
static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
if ( ext=="osgt" ) local_opt->setOptionString( local_opt->getOptionString() + " Ascii" );
if ( ext=="osgx" ) local_opt->setOptionString( local_opt->getOptionString() + " XML" );
return local_opt.release();
}
virtual ReadResult readObject( const std::string& file, const Options* options ) const
{
ReadResult result = ReadResult::FILE_LOADED;
std::string fileName = file;
Options* local_opt = prepareReading( result, fileName, options );
if ( !result.success() ) return result;
osgDB::ifstream istream( fileName.c_str(), std::ios::out|std::ios::binary );
return readObject( istream, local_opt );
}
virtual ReadResult readObject( std::istream& fin, const Options* options ) const
{
osg::ref_ptr<InputIterator> ii = readInputIterator(fin, options);
if ( !ii ) return ReadResult::FILE_NOT_HANDLED;
InputStream is( options );
if ( is.start(ii.get())!=InputStream::READ_OBJECT )
{
CATCH_EXCEPTION(is);
return ReadResult::FILE_NOT_HANDLED;
}
is.decompress(); CATCH_EXCEPTION(is);
osg::Object* obj = is.readObject(); CATCH_EXCEPTION(is);
return obj;
}
virtual ReadResult readImage( const std::string& file, const Options* options ) const
{
ReadResult result = ReadResult::FILE_LOADED;
std::string fileName = file;
Options* local_opt = prepareReading( result, fileName, options );
if ( !result.success() ) return result;
osgDB::ifstream istream( fileName.c_str(), std::ios::out|std::ios::binary );
return readImage( istream, local_opt );
}
virtual ReadResult readImage( std::istream& fin, const Options* options ) const
{
osg::ref_ptr<InputIterator> ii = readInputIterator(fin, options);
if ( !ii ) return ReadResult::FILE_NOT_HANDLED;
InputStream is( options );
if ( is.start(ii.get())!=InputStream::READ_IMAGE )
{
CATCH_EXCEPTION(is);
return ReadResult::FILE_NOT_HANDLED;
}
is.decompress(); CATCH_EXCEPTION(is);
osg::Image* image = is.readImage(); CATCH_EXCEPTION(is);
return image;
}
virtual ReadResult readNode( const std::string& file, const Options* options ) const
{
ReadResult result = ReadResult::FILE_LOADED;
std::string fileName = file;
Options* local_opt = prepareReading( result, fileName, options );
if ( !result.success() ) return result;
osgDB::ifstream istream( fileName.c_str(), std::ios::out|std::ios::binary );
return readNode( istream, local_opt );
}
virtual ReadResult readNode( std::istream& fin, const Options* options ) const
{
osg::ref_ptr<InputIterator> ii = readInputIterator(fin, options);
if ( !ii ) return ReadResult::FILE_NOT_HANDLED;
InputStream is( options );
if ( is.start(ii.get())!=InputStream::READ_SCENE )
{
CATCH_EXCEPTION(is);
return ReadResult::FILE_NOT_HANDLED;
}
is.decompress(); CATCH_EXCEPTION(is);
osg::Node* node = dynamic_cast<osg::Node*>(is.readObject()); CATCH_EXCEPTION(is);
return node;
}
Options* prepareWriting( WriteResult& result, const std::string& fileName, const Options* options ) const
{
std::string ext = osgDB::getFileExtension( fileName );
if ( !acceptsExtension(ext) ) result = WriteResult::FILE_NOT_HANDLED;
osg::ref_ptr<Options> local_opt = options ?
static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
if ( ext=="osgt" ) local_opt->setOptionString( local_opt->getOptionString() + " Ascii" );
if ( ext=="osgx" ) local_opt->setOptionString( local_opt->getOptionString() + " XML" );
return local_opt.release();
}
virtual WriteResult writeObject( const osg::Object& object, const std::string& fileName, const Options* options ) const
{
WriteResult result = WriteResult::FILE_SAVED;
Options* local_opt = prepareWriting( result, fileName, options );
if ( !result.success() ) return result;
osgDB::ofstream fout( fileName.c_str(), std::ios::out|std::ios::binary );
if ( !fout ) return WriteResult::ERROR_IN_WRITING_FILE;
result = writeObject( object, fout, local_opt );
fout.close();
return result;
}
virtual WriteResult writeObject( const osg::Object& object, std::ostream& fout, const Options* options ) const
{
osg::ref_ptr<OutputIterator> oi = writeInputIterator(fout, options);
OutputStream os( options );
os.start( oi.get(), OutputStream::WRITE_OBJECT ); CATCH_EXCEPTION(os);
os.writeObject( &object ); CATCH_EXCEPTION(os);
os.compress( &fout ); CATCH_EXCEPTION(os);
oi->flush();
if ( !os.getSchemaName().empty() )
{
osgDB::ofstream schemaStream( os.getSchemaName().c_str(), std::ios::out );
if ( !schemaStream.fail() ) os.writeSchema( schemaStream );
schemaStream.close();
}
if ( fout.fail() ) return WriteResult::ERROR_IN_WRITING_FILE;
return WriteResult::FILE_SAVED;
}
virtual WriteResult writeImage( const osg::Image& image, const std::string& fileName, const Options* options ) const
{
WriteResult result = WriteResult::FILE_SAVED;
Options* local_opt = prepareWriting( result, fileName, options );
if ( !result.success() ) return result;
osgDB::ofstream fout( fileName.c_str(), std::ios::out|std::ios::binary );
if ( !fout ) return WriteResult::ERROR_IN_WRITING_FILE;
result = writeImage( image, fout, local_opt );
fout.close();
return result;
}
virtual WriteResult writeImage( const osg::Image& image, std::ostream& fout, const Options* options ) const
{
osg::ref_ptr<OutputIterator> oi = writeInputIterator(fout, options);
OutputStream os( options );
os.start( oi.get(), OutputStream::WRITE_IMAGE ); CATCH_EXCEPTION(os);
os.writeImage( &image ); CATCH_EXCEPTION(os);
os.compress( &fout ); CATCH_EXCEPTION(os);
oi->flush();
if ( !os.getSchemaName().empty() )
{
osgDB::ofstream schemaStream( os.getSchemaName().c_str(), std::ios::out );
if ( !schemaStream.fail() ) os.writeSchema( schemaStream );
schemaStream.close();
}
if ( fout.fail() ) return WriteResult::ERROR_IN_WRITING_FILE;
return WriteResult::FILE_SAVED;
}
virtual WriteResult writeNode( const osg::Node& node, const std::string& fileName, const Options* options ) const
{
WriteResult result = WriteResult::FILE_SAVED;
Options* local_opt = prepareWriting( result, fileName, options );
if ( !result.success() ) return result;
osgDB::ofstream fout( fileName.c_str(), std::ios::out|std::ios::binary );
if ( !fout ) return WriteResult::ERROR_IN_WRITING_FILE;
result = writeNode( node, fout, local_opt );
fout.close();
return result;
}
virtual WriteResult writeNode( const osg::Node& node, std::ostream& fout, const Options* options ) const
{
osg::ref_ptr<OutputIterator> oi = writeInputIterator(fout, options);
OutputStream os( options );
os.start( oi.get(), OutputStream::WRITE_SCENE ); CATCH_EXCEPTION(os);
os.writeObject( &node ); CATCH_EXCEPTION(os);
os.compress( &fout ); CATCH_EXCEPTION(os);
oi->flush();
if ( !os.getSchemaName().empty() )
{
osgDB::ofstream schemaStream( os.getSchemaName().c_str(), std::ios::out );
if ( !schemaStream.fail() ) os.writeSchema( schemaStream );
schemaStream.close();
}
if ( fout.fail() ) return WriteResult::ERROR_IN_WRITING_FILE;
return WriteResult::FILE_SAVED;
}
};
REGISTER_OSGPLUGIN( osg2, ReaderWriterOSG2 )