change was to use doubles for reading and writing matrices regardless of type of Matrix being serialized. Change does break backwards compatibility though, so code path supporting original format has been left in for the time being. However, this code is not reliable enough and is over complicated compared to the simplified handling. Once the new code has been bedded down for a while I'll remove this code block.
837 lines
24 KiB
C++
837 lines
24 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 <osg/Notify>
|
|
#include <osg/ImageSequence>
|
|
#include <osgDB/ReadFile>
|
|
#include <osgDB/XmlParser>
|
|
#include <osgDB/FileNameUtils>
|
|
#include <osgDB/ObjectWrapper>
|
|
|
|
using namespace osgDB;
|
|
|
|
static std::string s_lastSchema;
|
|
|
|
InputStream::InputStream( const osgDB::Options* options )
|
|
: _byteSwap(0), _useSchemaData(false), _forceReadingImage(false), _dataDecompress(0)
|
|
{
|
|
if ( !options ) return;
|
|
_options = options;
|
|
|
|
std::string schema;
|
|
StringList optionList;
|
|
split( options->getOptionString(), optionList );
|
|
for ( StringList::iterator itr=optionList.begin(); itr!=optionList.end(); ++itr )
|
|
{
|
|
const std::string& option = *itr;
|
|
if ( option=="Ascii" )
|
|
{
|
|
// Omit this
|
|
}
|
|
else if ( option=="ForceReadingImage" )
|
|
{
|
|
_forceReadingImage = true;
|
|
}
|
|
else
|
|
{
|
|
StringList keyAndValues;
|
|
split( option, keyAndValues, '=' );
|
|
if ( keyAndValues.size()<2 ) continue;
|
|
|
|
if ( keyAndValues[0]=="SchemaFile" )
|
|
{
|
|
schema = keyAndValues[1];
|
|
if ( s_lastSchema!=schema )
|
|
{
|
|
osgDB::ifstream schemaStream( schema.c_str(), std::ios::in );
|
|
if ( !schemaStream.fail() ) readSchema( schemaStream );
|
|
schemaStream.close();
|
|
s_lastSchema = schema;
|
|
}
|
|
}
|
|
else
|
|
OSG_WARN << "InputStream: Unknown option " << option << std::endl;
|
|
}
|
|
}
|
|
if ( schema.empty() )
|
|
{
|
|
resetSchema();
|
|
s_lastSchema.clear();
|
|
}
|
|
}
|
|
|
|
InputStream::~InputStream()
|
|
{
|
|
if (_dataDecompress)
|
|
delete _dataDecompress;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec2b& v )
|
|
{
|
|
char x, y; *this >> x >> y;
|
|
v.set( x, y );
|
|
return *this;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec3b& v )
|
|
{
|
|
char x, y, z; *this >> x >> y >> z;
|
|
v.set( x, y, z );
|
|
return *this;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec4b& v )
|
|
{
|
|
char x, y, z, w; *this >> x >> y >> z >> w;
|
|
v.set( x, y, z, w );
|
|
return *this;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec4ub& v )
|
|
{
|
|
char r, g, b, a; *this >> r >> g >> b >> a;
|
|
v.set( r, g, b, a );
|
|
return *this;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec2s& v )
|
|
{ *this >> v.x() >> v.y(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec3s& v )
|
|
{ *this >> v.x() >> v.y() >> v.z(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec4s& v )
|
|
{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec2f& v )
|
|
{ *this >> v.x() >> v.y(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec3f& v )
|
|
{ *this >> v.x() >> v.y() >> v.z(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec4f& v )
|
|
{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec2d& v )
|
|
{ *this >> v.x() >> v.y(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec3d& v )
|
|
{ *this >> v.x() >> v.y() >> v.z(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Vec4d& v )
|
|
{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Quat& q )
|
|
{ *this >> q.x() >> q.y() >> q.z() >> q.w(); return *this; }
|
|
|
|
InputStream& InputStream::operator>>( osg::Plane& p )
|
|
{
|
|
double p0, p1, p2, p3; *this >> p0 >> p1 >> p2 >> p3;
|
|
p.set( p0, p1, p2, p3 ); return *this;
|
|
}
|
|
|
|
#if 0
|
|
InputStream& InputStream::operator>>( osg::Matrixf& mat )
|
|
{
|
|
ObjectProperty property("");
|
|
*this >> property >> BEGIN_BRACKET;
|
|
|
|
if (property._name == "Matrixf")
|
|
{
|
|
// stream has same type as what we want to read so read directly
|
|
for ( int r=0; r<4; ++r )
|
|
{
|
|
*this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
|
|
}
|
|
}
|
|
else if (property._name == "Matrixd")
|
|
{
|
|
// stream has different type than what we want to read so read stream into
|
|
// a temporary and then copy across to the final matrix
|
|
double value;
|
|
for ( int r=0; r<4; ++r )
|
|
{
|
|
for ( int c=0; c<4; ++c)
|
|
{
|
|
*this >> value;
|
|
mat(r,c) = static_cast<float>(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
*this >> END_BRACKET;
|
|
return *this;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Matrixd& mat )
|
|
{
|
|
ObjectProperty property("");
|
|
*this >> property >> BEGIN_BRACKET;
|
|
|
|
if (property._name == "Matrixf")
|
|
{
|
|
// stream has different type than what we want to read so read stream into
|
|
// a temporary and then copy across to the final matrix
|
|
float value;
|
|
for ( int r=0; r<4; ++r )
|
|
{
|
|
for ( int c=0; c<4; ++c)
|
|
{
|
|
*this >> value;
|
|
mat(r,c) = static_cast<float>(value);
|
|
}
|
|
}
|
|
}
|
|
else if (property._name == "Matrixd")
|
|
{
|
|
// stream has same type as what we want to read so read directly
|
|
for ( int r=0; r<4; ++r )
|
|
{
|
|
*this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
|
|
}
|
|
}
|
|
|
|
*this >> END_BRACKET;
|
|
return *this;
|
|
}
|
|
#else
|
|
InputStream& InputStream::operator>>( osg::Matrixf& mat )
|
|
{
|
|
*this >> BEGIN_BRACKET;
|
|
|
|
// stream has different type than what we want to read so read stream into
|
|
// a temporary and then copy across to the final matrix
|
|
double value;
|
|
for ( int r=0; r<4; ++r )
|
|
{
|
|
for ( int c=0; c<4; ++c)
|
|
{
|
|
*this >> value;
|
|
mat(r,c) = static_cast<float>(value);
|
|
}
|
|
}
|
|
|
|
*this >> END_BRACKET;
|
|
return *this;
|
|
}
|
|
|
|
InputStream& InputStream::operator>>( osg::Matrixd& mat )
|
|
{
|
|
*this >> BEGIN_BRACKET;
|
|
|
|
for ( int r=0; r<4; ++r )
|
|
{
|
|
*this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
|
|
}
|
|
|
|
*this >> END_BRACKET;
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
osg::Array* InputStream::readArray()
|
|
{
|
|
osg::ref_ptr<osg::Array> array = NULL;
|
|
|
|
unsigned int id = 0;
|
|
*this >> PROPERTY("ArrayID") >> id;
|
|
|
|
ArrayMap::iterator itr = _arrayMap.find( id );
|
|
if ( itr!=_arrayMap.end() )
|
|
{
|
|
return itr->second.get();
|
|
}
|
|
|
|
DEF_MAPPEE(ArrayType, type);
|
|
*this >> type;
|
|
switch ( type.get() )
|
|
{
|
|
case ID_BYTE_ARRAY:
|
|
{
|
|
osg::ByteArray* ba = new osg::ByteArray;
|
|
readArrayImplementation( ba, CHAR_SIZE, true );
|
|
array = ba;
|
|
}
|
|
break;
|
|
case ID_UBYTE_ARRAY:
|
|
{
|
|
osg::UByteArray* uba = new osg::UByteArray;
|
|
readArrayImplementation( uba, CHAR_SIZE, true );
|
|
array = uba;
|
|
}
|
|
break;
|
|
case ID_SHORT_ARRAY:
|
|
{
|
|
osg::ShortArray* sa = new osg::ShortArray;
|
|
readArrayImplementation( sa, SHORT_SIZE, true );
|
|
array = sa;
|
|
}
|
|
break;
|
|
case ID_USHORT_ARRAY:
|
|
{
|
|
osg::UShortArray* usa = new osg::UShortArray;
|
|
readArrayImplementation( usa, SHORT_SIZE, true );
|
|
array = usa;
|
|
}
|
|
break;
|
|
case ID_INT_ARRAY:
|
|
{
|
|
osg::IntArray* ia = new osg::IntArray;
|
|
readArrayImplementation( ia, INT_SIZE, true );
|
|
array = ia;
|
|
}
|
|
break;
|
|
case ID_UINT_ARRAY:
|
|
{
|
|
osg::UIntArray* uia = new osg::UIntArray;
|
|
readArrayImplementation( uia, INT_SIZE, true );
|
|
array = uia;
|
|
}
|
|
break;
|
|
case ID_FLOAT_ARRAY:
|
|
{
|
|
osg::FloatArray* fa = new osg::FloatArray;
|
|
readArrayImplementation( fa, FLOAT_SIZE, true );
|
|
array = fa;
|
|
}
|
|
break;
|
|
case ID_DOUBLE_ARRAY:
|
|
{
|
|
osg::DoubleArray* da = new osg::DoubleArray;
|
|
readArrayImplementation( da, DOUBLE_SIZE, true );
|
|
array = da;
|
|
}
|
|
break;
|
|
case ID_VEC2B_ARRAY:
|
|
{
|
|
osg::Vec2bArray* va = new osg::Vec2bArray;
|
|
readArrayImplementation( va, 2*CHAR_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC3B_ARRAY:
|
|
{
|
|
osg::Vec3bArray* va = new osg::Vec3bArray;
|
|
readArrayImplementation( va, 3*CHAR_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC4B_ARRAY:
|
|
{
|
|
osg::Vec4bArray* va = new osg::Vec4bArray;
|
|
readArrayImplementation( va, 4*CHAR_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC4UB_ARRAY:
|
|
{
|
|
osg::Vec4ubArray* va = new osg::Vec4ubArray;
|
|
readArrayImplementation( va, 4*CHAR_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC2S_ARRAY:
|
|
{
|
|
osg::Vec2sArray* va = new osg::Vec2sArray;
|
|
readArrayImplementation( va, 2*SHORT_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC3S_ARRAY:
|
|
{
|
|
osg::Vec3sArray* va = new osg::Vec3sArray;
|
|
readArrayImplementation( va, 3*SHORT_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC4S_ARRAY:
|
|
{
|
|
osg::Vec4sArray* va = new osg::Vec4sArray;
|
|
readArrayImplementation( va, 4*SHORT_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC2_ARRAY:
|
|
{
|
|
osg::Vec2Array* va = new osg::Vec2Array;
|
|
readArrayImplementation( va, 2*FLOAT_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC3_ARRAY:
|
|
{
|
|
osg::Vec3Array* va = new osg::Vec3Array;
|
|
readArrayImplementation( va, 3*FLOAT_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC4_ARRAY:
|
|
{
|
|
osg::Vec4Array* va = new osg::Vec4Array;
|
|
readArrayImplementation( va, 4*FLOAT_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC2D_ARRAY:
|
|
{
|
|
osg::Vec2dArray* va = new osg::Vec2dArray;
|
|
readArrayImplementation( va, 2*DOUBLE_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC3D_ARRAY:
|
|
{
|
|
osg::Vec3dArray* va = new osg::Vec3dArray;
|
|
readArrayImplementation( va, 3*DOUBLE_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
case ID_VEC4D_ARRAY:
|
|
{
|
|
osg::Vec4dArray* va = new osg::Vec4dArray;
|
|
readArrayImplementation( va, 4*DOUBLE_SIZE );
|
|
array = va;
|
|
}
|
|
break;
|
|
default:
|
|
throwException( "InputStream::readArray(): Unsupported array type." );
|
|
}
|
|
|
|
if ( getException() ) return NULL;
|
|
_arrayMap[id] = array;
|
|
|
|
return array.release();
|
|
}
|
|
|
|
osg::PrimitiveSet* InputStream::readPrimitiveSet()
|
|
{
|
|
osg::ref_ptr<osg::PrimitiveSet> primitive = NULL;
|
|
|
|
DEF_MAPPEE(PrimitiveType, type);
|
|
DEF_MAPPEE(PrimitiveType, mode);
|
|
*this >> type >> mode;
|
|
|
|
switch ( type.get() )
|
|
{
|
|
case ID_DRAWARRAYS:
|
|
{
|
|
int first = 0, count = 0;
|
|
*this >> first >> count;
|
|
osg::DrawArrays* da = new osg::DrawArrays( mode.get(), first, count );
|
|
primitive = da;
|
|
}
|
|
break;
|
|
case ID_DRAWARRAY_LENGTH:
|
|
{
|
|
int first = 0, value = 0; unsigned int size = 0;
|
|
*this >> first >> size >> BEGIN_BRACKET;
|
|
osg::DrawArrayLengths* dl = new osg::DrawArrayLengths( mode.get(), first );
|
|
for ( unsigned int i=0; i<size; ++i )
|
|
{
|
|
*this >> value;
|
|
dl->push_back( value );
|
|
}
|
|
*this >> END_BRACKET;
|
|
primitive = dl;
|
|
}
|
|
break;
|
|
case ID_DRAWELEMENTS_UBYTE:
|
|
{
|
|
osg::DrawElementsUByte* de = new osg::DrawElementsUByte( mode.get() );
|
|
unsigned int size = 0; unsigned char value = 0;
|
|
*this >> size >> BEGIN_BRACKET;
|
|
for ( unsigned int i=0; i<size; ++i )
|
|
{
|
|
*this >> value;
|
|
de->push_back( value );
|
|
}
|
|
*this >> END_BRACKET;
|
|
primitive = de;
|
|
}
|
|
break;
|
|
case ID_DRAWELEMENTS_USHORT:
|
|
{
|
|
osg::DrawElementsUShort* de = new osg::DrawElementsUShort( mode.get() );
|
|
unsigned int size = 0; unsigned short value = 0;
|
|
*this >> size >> BEGIN_BRACKET;
|
|
for ( unsigned int i=0; i<size; ++i )
|
|
{
|
|
*this >> value;
|
|
de->push_back( value );
|
|
}
|
|
*this >> END_BRACKET;
|
|
primitive = de;
|
|
}
|
|
break;
|
|
case ID_DRAWELEMENTS_UINT:
|
|
{
|
|
osg::DrawElementsUInt* de = new osg::DrawElementsUInt( mode.get() );
|
|
unsigned int size = 0, value = 0;
|
|
*this >> size >> BEGIN_BRACKET;
|
|
for ( unsigned int i=0; i<size; ++i )
|
|
{
|
|
*this >> value;
|
|
de->push_back( value );
|
|
}
|
|
*this >> END_BRACKET;
|
|
primitive = de;
|
|
}
|
|
break;
|
|
default:
|
|
throwException( "InputStream::readPrimitiveSet(): Unsupported array type." );
|
|
}
|
|
|
|
if ( getException() ) return NULL;
|
|
return primitive.release();
|
|
}
|
|
|
|
osg::Image* InputStream::readImage()
|
|
{
|
|
std::string className="osg::Image";
|
|
unsigned int id = 0;
|
|
|
|
*this >> PROPERTY("UniqueID") >> id;
|
|
if ( getException() ) return NULL;
|
|
|
|
IdentifierMap::iterator itr = _identifierMap.find( id );
|
|
if ( itr!=_identifierMap.end() )
|
|
{
|
|
return static_cast<osg::Image*>( itr->second.get() );
|
|
}
|
|
|
|
std::string name;
|
|
int writeHint, decision = IMAGE_EXTERNAL;
|
|
*this >> PROPERTY("FileName"); readWrappedString(name);
|
|
*this >> PROPERTY("WriteHint") >> writeHint >> decision;
|
|
if ( getException() ) return NULL;
|
|
|
|
osg::ref_ptr<osg::Image> image = NULL;
|
|
bool readFromExternal = true;
|
|
switch ( decision )
|
|
{
|
|
case IMAGE_INLINE_DATA:
|
|
if ( isBinary() )
|
|
{
|
|
image = new osg::Image;
|
|
|
|
// _origin, _s & _t & _r, _internalTextureFormat
|
|
int origin, s, t, r, internalFormat;
|
|
*this >> origin >> s >> t >> r >> internalFormat;
|
|
|
|
// _pixelFormat, _dataType, _packing, _allocationMode
|
|
int pixelFormat, dataType, packing, mode;
|
|
*this >> pixelFormat >> dataType >> packing >> mode;
|
|
|
|
// _data
|
|
unsigned int size = 0; *this >> size;
|
|
if ( size )
|
|
{
|
|
char* data = new char[size];
|
|
if ( !data )
|
|
throwException( "InputStream::readImage() Out of memory." );
|
|
if ( getException() ) return NULL;
|
|
|
|
readCharArray( data, size );
|
|
image->setOrigin( (osg::Image::Origin)origin );
|
|
image->setImage( s, t, r, internalFormat, pixelFormat, dataType,
|
|
(unsigned char*)data, (osg::Image::AllocationMode)mode, packing );
|
|
}
|
|
|
|
// _mipmapData
|
|
unsigned int levelSize = readSize();
|
|
osg::Image::MipmapDataType levels(levelSize);
|
|
for ( unsigned int i=0; i<levelSize; ++i )
|
|
{
|
|
*this >> levels[i];
|
|
}
|
|
if ( levelSize>0 )
|
|
image->setMipmapLevels( levels );
|
|
readFromExternal = false;
|
|
}
|
|
break;
|
|
case IMAGE_INLINE_FILE:
|
|
if ( isBinary() )
|
|
{
|
|
unsigned int size = readSize();
|
|
if ( size>0 )
|
|
{
|
|
char* data = new char[size];
|
|
if ( !data )
|
|
throwException( "InputStream::readImage(): Out of memory." );
|
|
if ( getException() ) return NULL;
|
|
readCharArray( data, size );
|
|
|
|
std::string ext = osgDB::getFileExtension( name );
|
|
osgDB::ReaderWriter* reader =
|
|
osgDB::Registry::instance()->getReaderWriterForExtension( ext );
|
|
if ( reader )
|
|
{
|
|
std::stringstream inputStream;
|
|
inputStream.write( data, size );
|
|
|
|
osgDB::ReaderWriter::ReadResult rr = reader->readImage( inputStream );
|
|
if ( rr.validImage() )
|
|
image = rr.takeImage();
|
|
else
|
|
{
|
|
OSG_WARN << "InputStream::readImage(): "
|
|
<< rr.message() << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OSG_WARN << "InputStream::readImage(): Unable to find a plugin for "
|
|
<< ext << std::endl;
|
|
}
|
|
delete[] data;
|
|
}
|
|
readFromExternal = false;
|
|
}
|
|
break;
|
|
case IMAGE_EXTERNAL: case IMAGE_WRITE_OUT:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( readFromExternal )
|
|
{
|
|
image = osgDB::readImageFile( name, getOptions() );
|
|
if ( !image && _forceReadingImage ) image = new osg::Image;
|
|
}
|
|
if ( image.valid() )
|
|
{
|
|
image->setFileName( name );
|
|
image->setWriteHint( (osg::Image::WriteHint)writeHint );
|
|
}
|
|
|
|
image = static_cast<osg::Image*>( readObjectFields(className, image.get()) );
|
|
|
|
_identifierMap[id] = image;
|
|
|
|
return image.release();
|
|
}
|
|
|
|
osg::Object* InputStream::readObject( osg::Object* existingObj )
|
|
{
|
|
std::string className;
|
|
unsigned int id = 0;
|
|
*this >> className >> BEGIN_BRACKET >> PROPERTY("UniqueID") >> id;
|
|
if ( getException() ) return NULL;
|
|
|
|
IdentifierMap::iterator itr = _identifierMap.find( id );
|
|
if ( itr!=_identifierMap.end() )
|
|
{
|
|
advanceToCurrentEndBracket();
|
|
return itr->second.get();
|
|
}
|
|
|
|
osg::ref_ptr<osg::Object> obj = readObjectFields( className );
|
|
|
|
_identifierMap[id] = obj;
|
|
|
|
advanceToCurrentEndBracket();
|
|
|
|
return obj.release();
|
|
}
|
|
|
|
osg::Object* InputStream::readObjectFields( const std::string& className, osg::Object* existingObj )
|
|
{
|
|
ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( className );
|
|
if ( !wrapper )
|
|
{
|
|
OSG_WARN << "InputStream::readObject(): Unsupported wrapper class "
|
|
<< className << std::endl;
|
|
return NULL;
|
|
}
|
|
_fields.push_back( className );
|
|
|
|
osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->getProto()->cloneType();
|
|
if ( obj.valid() )
|
|
{
|
|
const StringList& associates = wrapper->getAssociates();
|
|
for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
|
|
{
|
|
ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr);
|
|
if ( !assocWrapper )
|
|
{
|
|
OSG_WARN << "InputStream::readObject(): Unsupported associated class "
|
|
<< *itr << std::endl;
|
|
continue;
|
|
}
|
|
_fields.push_back( assocWrapper->getName() );
|
|
|
|
assocWrapper->read( *this, *obj );
|
|
if ( getException() ) return NULL;
|
|
|
|
_fields.pop_back();
|
|
}
|
|
}
|
|
_fields.pop_back();
|
|
return obj.release();
|
|
}
|
|
|
|
void InputStream::readSchema( std::istream& fin )
|
|
{
|
|
// Read from external ascii stream
|
|
std::string line;
|
|
while ( std::getline(fin, line) )
|
|
{
|
|
if ( line[0]=='#' ) continue; // Comment
|
|
|
|
StringList keyAndValue;
|
|
split( line, keyAndValue, '=' );
|
|
if ( keyAndValue.size()<2 ) continue;
|
|
|
|
setWrapperSchema( osgDB::trimEnclosingSpaces(keyAndValue[0]),
|
|
osgDB::trimEnclosingSpaces(keyAndValue[1]) );
|
|
}
|
|
}
|
|
|
|
InputStream::ReadType InputStream::start( InputIterator* inIterator )
|
|
{
|
|
_fields.clear();
|
|
_fields.push_back( "Start" );
|
|
|
|
ReadType type = READ_UNKNOWN;
|
|
_in = inIterator;
|
|
if ( !_in )
|
|
throwException( "InputStream: Null stream specified." );
|
|
if ( getException() ) return type;
|
|
|
|
// Check OSG header information
|
|
unsigned int version = 0;
|
|
if ( isBinary() )
|
|
{
|
|
unsigned int typeValue;
|
|
*this >> typeValue >> version;
|
|
type = static_cast<ReadType>(typeValue);
|
|
|
|
unsigned int attributes; *this >> attributes;
|
|
if ( attributes&0x2 ) _useSchemaData = true;
|
|
}
|
|
if ( !isBinary() )
|
|
{
|
|
std::string typeString; *this >> typeString;
|
|
if ( typeString=="Scene" ) type = READ_SCENE;
|
|
else if ( typeString=="Image" ) type = READ_IMAGE;
|
|
else if ( typeString=="Object" ) type = READ_OBJECT;
|
|
|
|
std::string osgName, osgVersion;
|
|
*this >> PROPERTY("#Version") >> version;
|
|
*this >> PROPERTY("#Generator") >> osgName >> osgVersion;
|
|
}
|
|
|
|
// Check file version
|
|
if ( version!=PLUGIN_VERSION )
|
|
{
|
|
OSG_WARN << "InputStream: Input data version " << version
|
|
<< " may be incompatible with current reader version "
|
|
<< PLUGIN_VERSION << std::endl;
|
|
}
|
|
_fields.pop_back();
|
|
return type;
|
|
}
|
|
|
|
void InputStream::decompress()
|
|
{
|
|
if ( !isBinary() ) return;
|
|
_fields.clear();
|
|
|
|
std::string compressorName; *this >> compressorName;
|
|
if ( compressorName!="0" )
|
|
{
|
|
std::string data;
|
|
_fields.push_back( "Decompression" );
|
|
|
|
BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName);
|
|
if ( !compressor )
|
|
{
|
|
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;
|
|
|
|
_dataDecompress = new std::stringstream(data);
|
|
_in->setStream( _dataDecompress );
|
|
_fields.pop_back();
|
|
}
|
|
|
|
if ( _useSchemaData )
|
|
{
|
|
_fields.push_back( "SchemaData" );
|
|
std::string schemaSource; *this >> schemaSource;
|
|
std::istringstream iss( schemaSource );
|
|
readSchema( iss );
|
|
_fields.pop_back();
|
|
}
|
|
}
|
|
|
|
// PROTECTED METHODS
|
|
|
|
void InputStream::setWrapperSchema( const std::string& name, const std::string& properties )
|
|
{
|
|
ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(name);
|
|
if ( !wrapper )
|
|
{
|
|
OSG_WARN << "InputStream::setSchema(): Unsupported wrapper class "
|
|
<< name << std::endl;
|
|
return;
|
|
}
|
|
|
|
StringList schema;
|
|
split( properties, schema );
|
|
wrapper->readSchema( schema );
|
|
}
|
|
|
|
void InputStream::resetSchema()
|
|
{
|
|
const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap();
|
|
for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin();
|
|
itr!=wrappers.end(); ++itr )
|
|
{
|
|
ObjectWrapper* wrapper = itr->second.get();
|
|
wrapper->resetSchema();
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
void InputStream::readArrayImplementation( T* a, int read_size, bool useByteSwap )
|
|
{
|
|
int size = 0;
|
|
*this >> size >> BEGIN_BRACKET;
|
|
if ( size )
|
|
{
|
|
a->resize( size );
|
|
if ( isBinary() )
|
|
{
|
|
readCharArray( (char*)&((*a)[0]), read_size*size ); checkStream();
|
|
if ( useByteSwap && _byteSwap )
|
|
{
|
|
for ( int i=0; i<size; ++i )
|
|
osg::swapBytes( (char*)&((*a)[i]), read_size );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( int i=0; i<size; ++i )
|
|
*this >> (*a)[i];
|
|
}
|
|
}
|
|
*this >> END_BRACKET;
|
|
}
|