root/OpenSceneGraph/trunk/src/osgDB/InputStream.cpp @ 13584

Revision 13584, 27.7 kB (checked in by robert, 17 hours ago)

Added handling of Drawables added directly to scene graph without Geode decorating them.

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13// Written by Wang Rui, (C) 2010
14
15#include <osg/Notify>
16#include <osg/ImageSequence>
17#include <osgDB/ReadFile>
18#include <osgDB/XmlParser>
19#include <osgDB/FileNameUtils>
20#include <osgDB/ObjectWrapper>
21
22using namespace osgDB;
23
24static std::string s_lastSchema;
25
26InputStream::InputStream( const osgDB::Options* options )
27    :   _fileVersion(0), _useSchemaData(false), _forceReadingImage(false), _dataDecompress(0)
28{
29    BEGIN_BRACKET.set( "{", +INDENT_VALUE );
30    END_BRACKET.set( "}", -INDENT_VALUE );
31
32    if ( !options ) return;
33    _options = options;
34
35    if ( options->getPluginStringData("ForceReadingImage")=="true" )
36        _forceReadingImage = true;
37
38    if ( !options->getPluginStringData("CustomDomains").empty() )
39    {
40        StringList domains, keyAndValue;
41        split( options->getPluginStringData("CustomDomains"), domains, ';' );
42        for ( unsigned int i=0; i<domains.size(); ++i )
43        {
44            split( domains[i], keyAndValue, ':' );
45            if ( keyAndValue.size()>1 )
46                _domainVersionMap[keyAndValue.front()] = atoi(keyAndValue.back().c_str());
47        }
48    }
49
50    std::string schema;
51    if ( !options->getPluginStringData("SchemaFile").empty() )
52    {
53        schema = options->getPluginStringData("SchemaFile");
54        if ( s_lastSchema!=schema )
55        {
56            osgDB::ifstream schemaStream( schema.c_str(), std::ios::in );
57            if ( !schemaStream.fail() ) readSchema( schemaStream );
58            schemaStream.close();
59            s_lastSchema = schema;
60        }
61    }
62
63    if ( schema.empty() )
64    {
65        resetSchema();
66        s_lastSchema.clear();
67    }
68}
69
70InputStream::~InputStream()
71{
72    if (_dataDecompress)
73        delete _dataDecompress;
74}
75
76int InputStream::getFileVersion( const std::string& d ) const
77{
78    if ( d.empty() ) return _fileVersion;
79    VersionMap::const_iterator itr = _domainVersionMap.find(d);
80    return itr==_domainVersionMap.end() ? 0 : itr->second;
81}
82
83InputStream& InputStream::operator>>( osg::Vec2b& v )
84{
85    char x, y; *this >> x >> y;
86    v.set( x, y );
87    return *this;
88}
89
90InputStream& InputStream::operator>>( osg::Vec3b& v )
91{
92    char x, y, z; *this >> x >> y >> z;
93    v.set( x, y, z );
94    return *this;
95}
96
97InputStream& InputStream::operator>>( osg::Vec4b& v )
98{
99    char x, y, z, w; *this >> x >> y >> z >> w;
100    v.set( x, y, z, w );
101    return *this;
102}
103
104InputStream& InputStream::operator>>( osg::Vec2ub& v )
105{
106    unsigned char x, y; *this >> x >> y;
107    v.set( x, y );
108    return *this;
109}
110
111InputStream& InputStream::operator>>( osg::Vec3ub& v )
112{
113    unsigned char x, y, z; *this >> x >> y >> z;
114    v.set( x, y, z );
115    return *this;
116}
117
118InputStream& InputStream::operator>>( osg::Vec4ub& v )
119{
120    unsigned char r, g, b, a; *this >> r >> g >> b >> a;
121    v.set( r, g, b, a );
122    return *this;
123}
124
125InputStream& InputStream::operator>>( osg::Vec2s& v )
126{ *this >> v.x() >> v.y(); return *this; }
127
128InputStream& InputStream::operator>>( osg::Vec3s& v )
129{ *this >> v.x() >> v.y() >> v.z(); return *this; }
130
131InputStream& InputStream::operator>>( osg::Vec4s& v )
132{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
133
134InputStream& InputStream::operator>>( osg::Vec2us& v )
135{ *this >> v.x() >> v.y(); return *this; }
136
137InputStream& InputStream::operator>>( osg::Vec3us& v )
138{ *this >> v.x() >> v.y() >> v.z(); return *this; }
139
140InputStream& InputStream::operator>>( osg::Vec4us& v )
141{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
142
143
144InputStream& InputStream::operator>>( osg::Vec2i& v )
145{ *this >> v.x() >> v.y(); return *this; }
146
147InputStream& InputStream::operator>>( osg::Vec3i& v )
148{ *this >> v.x() >> v.y() >> v.z(); return *this; }
149
150InputStream& InputStream::operator>>( osg::Vec4i& v )
151{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
152
153
154InputStream& InputStream::operator>>( osg::Vec2ui& v )
155{ *this >> v.x() >> v.y(); return *this; }
156
157InputStream& InputStream::operator>>( osg::Vec3ui& v )
158{ *this >> v.x() >> v.y() >> v.z(); return *this; }
159
160InputStream& InputStream::operator>>( osg::Vec4ui& v )
161{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
162
163
164InputStream& InputStream::operator>>( osg::Vec2f& v )
165{ *this >> v.x() >> v.y(); return *this; }
166
167InputStream& InputStream::operator>>( osg::Vec3f& v )
168{ *this >> v.x() >> v.y() >> v.z(); return *this; }
169
170InputStream& InputStream::operator>>( osg::Vec4f& v )
171{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
172
173
174InputStream& InputStream::operator>>( osg::Vec2d& v )
175{ *this >> v.x() >> v.y(); return *this; }
176
177InputStream& InputStream::operator>>( osg::Vec3d& v )
178{ *this >> v.x() >> v.y() >> v.z(); return *this; }
179
180InputStream& InputStream::operator>>( osg::Vec4d& v )
181{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
182
183
184InputStream& InputStream::operator>>( osg::Quat& q )
185{ *this >> q.x() >> q.y() >> q.z() >> q.w(); return *this; }
186
187InputStream& InputStream::operator>>( osg::Plane& p )
188{
189    double p0, p1, p2, p3; *this >> p0 >> p1 >> p2 >> p3;
190    p.set( p0, p1, p2, p3 ); return *this;
191}
192
193#if 0
194InputStream& InputStream::operator>>( osg::Matrixf& mat )
195{
196   ObjectProperty property("");
197   *this >> property  >> BEGIN_BRACKET;
198
199   if (property._name == "Matrixf")
200   {
201        // stream has same type as what we want to read so read directly
202        for ( int r=0; r<4; ++r )
203        {
204            *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
205        }
206   }
207   else if (property._name == "Matrixd")
208   {
209        // stream has different type than what we want to read so read stream into
210        // a temporary and then copy across to the final matrix
211        double value;
212        for ( int r=0; r<4; ++r )
213        {
214            for ( int c=0; c<4; ++c)
215            {
216                *this >> value;
217                mat(r,c) = static_cast<float>(value);
218            }
219        }
220   }
221
222   *this >> END_BRACKET;
223   return *this;
224}
225
226InputStream& InputStream::operator>>( osg::Matrixd& mat )
227{
228   ObjectProperty property("");
229   *this >> property  >> BEGIN_BRACKET;
230
231   if (property._name == "Matrixf")
232   {
233        // stream has different type than what we want to read so read stream into
234        // a temporary and then copy across to the final matrix
235        float value;
236        for ( int r=0; r<4; ++r )
237        {
238            for ( int c=0; c<4; ++c)
239            {
240                *this >> value;
241                mat(r,c) = static_cast<float>(value);
242            }
243        }
244   }
245   else if (property._name == "Matrixd")
246   {
247        // stream has same type as what we want to read so read directly
248        for ( int r=0; r<4; ++r )
249        {
250            *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
251        }
252   }
253
254   *this >> END_BRACKET;
255   return *this;
256}
257#else
258InputStream& InputStream::operator>>( osg::Matrixf& mat )
259{
260    *this >> BEGIN_BRACKET;
261
262    // stream has different type than what we want to read so read stream into
263    // a temporary and then copy across to the final matrix
264    double value;
265    for ( int r=0; r<4; ++r )
266    {
267        for ( int c=0; c<4; ++c)
268        {
269            *this >> value;
270            mat(r,c) = static_cast<float>(value);
271        }
272    }
273
274    *this >> END_BRACKET;
275    return *this;
276}
277
278InputStream& InputStream::operator>>( osg::Matrixd& mat )
279{
280    *this >> BEGIN_BRACKET;
281
282    for ( int r=0; r<4; ++r )
283    {
284        *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
285    }
286
287    *this >> END_BRACKET;
288    return *this;
289}
290#endif
291
292osg::Array* InputStream::readArray()
293{
294    osg::ref_ptr<osg::Array> array = NULL;
295
296    unsigned int id = 0;
297    *this >> PROPERTY("ArrayID") >> id;
298
299    ArrayMap::iterator itr = _arrayMap.find( id );
300    if ( itr!=_arrayMap.end() )
301    {
302        return itr->second.get();
303    }
304
305    DEF_MAPPEE(ArrayType, type);
306    *this >> type;
307    switch ( type.get() )
308    {
309    case ID_BYTE_ARRAY:
310        {
311            osg::ByteArray* ba = new osg::ByteArray;
312            readArrayImplementation( ba, 1, CHAR_SIZE);
313            array = ba;
314        }
315        break;
316    case ID_UBYTE_ARRAY:
317        {
318            osg::UByteArray* uba = new osg::UByteArray;
319            readArrayImplementation( uba, 1, CHAR_SIZE );
320            array = uba;
321        }
322        break;
323    case ID_SHORT_ARRAY:
324        {
325            osg::ShortArray* sa = new osg::ShortArray;
326            readArrayImplementation( sa, 1, SHORT_SIZE );
327            array = sa;
328        }
329        break;
330    case ID_USHORT_ARRAY:
331        {
332            osg::UShortArray* usa = new osg::UShortArray;
333            readArrayImplementation( usa, 1, SHORT_SIZE );
334            array = usa;
335        }
336        break;
337    case ID_INT_ARRAY:
338        {
339            osg::IntArray* ia = new osg::IntArray;
340            readArrayImplementation( ia, 1, INT_SIZE );
341            array = ia;
342        }
343        break;
344    case ID_UINT_ARRAY:
345        {
346            osg::UIntArray* uia = new osg::UIntArray;
347            readArrayImplementation( uia, 1, INT_SIZE );
348            array = uia;
349        }
350        break;
351    case ID_FLOAT_ARRAY:
352        {
353            osg::FloatArray* fa = new osg::FloatArray;
354            readArrayImplementation( fa, 1, FLOAT_SIZE );
355            array = fa;
356        }
357        break;
358    case ID_DOUBLE_ARRAY:
359        {
360            osg::DoubleArray* da = new osg::DoubleArray;
361            readArrayImplementation( da, 1, DOUBLE_SIZE );
362            array = da;
363        }
364        break;
365    case ID_VEC2B_ARRAY:
366        {
367            osg::Vec2bArray* va = new osg::Vec2bArray;
368            readArrayImplementation( va, 2, CHAR_SIZE );
369            array = va;
370        }
371        break;
372    case ID_VEC3B_ARRAY:
373        {
374            osg::Vec3bArray* va = new osg::Vec3bArray;
375            readArrayImplementation( va, 3, CHAR_SIZE );
376            array = va;
377        }
378        break;
379    case ID_VEC4B_ARRAY:
380        {
381            osg::Vec4bArray* va = new osg::Vec4bArray;
382            readArrayImplementation( va, 4, CHAR_SIZE );
383            array = va;
384        }
385        break;
386    case ID_VEC2UB_ARRAY:
387        {
388            osg::Vec2ubArray* va = new osg::Vec2ubArray;
389            readArrayImplementation( va, 2, CHAR_SIZE );
390            array = va;
391        }
392        break;
393    case ID_VEC3UB_ARRAY:
394        {
395            osg::Vec3ubArray* va = new osg::Vec3ubArray;
396            readArrayImplementation( va, 3, CHAR_SIZE );
397            array = va;
398        }
399        break;
400    case ID_VEC4UB_ARRAY:
401        {
402            osg::Vec4ubArray* va = new osg::Vec4ubArray;
403            readArrayImplementation( va, 4, CHAR_SIZE );
404            array = va;
405        }
406        break;
407    case ID_VEC2S_ARRAY:
408        {
409            osg::Vec2sArray* va = new osg::Vec2sArray;
410            readArrayImplementation( va, 2, SHORT_SIZE );
411            array = va;
412        }
413        break;
414    case ID_VEC3S_ARRAY:
415        {
416            osg::Vec3sArray* va = new osg::Vec3sArray;
417            readArrayImplementation( va, 3, SHORT_SIZE );
418            array = va;
419        }
420        break;
421    case ID_VEC4S_ARRAY:
422        {
423            osg::Vec4sArray* va = new osg::Vec4sArray;
424            readArrayImplementation( va, 4, SHORT_SIZE );
425            array = va;
426        }
427        break;
428    case ID_VEC2US_ARRAY:
429        {
430            osg::Vec2usArray* va = new osg::Vec2usArray;
431            readArrayImplementation( va, 2, SHORT_SIZE );
432            array = va;
433        }
434        break;
435    case ID_VEC3US_ARRAY:
436        {
437            osg::Vec3usArray* va = new osg::Vec3usArray;
438            readArrayImplementation( va, 3, SHORT_SIZE );
439            array = va;
440        }
441        break;
442    case ID_VEC4US_ARRAY:
443        {
444            osg::Vec4usArray* va = new osg::Vec4usArray;
445            readArrayImplementation( va, 4, SHORT_SIZE );
446            array = va;
447        }
448        break;
449    case ID_VEC2_ARRAY:
450        {
451            osg::Vec2Array* va = new osg::Vec2Array;
452            readArrayImplementation( va, 2, FLOAT_SIZE );
453            array = va;
454        }
455        break;
456    case ID_VEC3_ARRAY:
457        {
458            osg::Vec3Array* va = new osg::Vec3Array;
459            readArrayImplementation( va, 3, FLOAT_SIZE );
460            array = va;
461        }
462        break;
463    case ID_VEC4_ARRAY:
464        {
465            osg::Vec4Array* va = new osg::Vec4Array;
466            readArrayImplementation( va, 4, FLOAT_SIZE );
467            array = va;
468        }
469        break;
470    case ID_VEC2D_ARRAY:
471        {
472            osg::Vec2dArray* va = new osg::Vec2dArray;
473            readArrayImplementation( va, 2, DOUBLE_SIZE );
474            array = va;
475        }
476        break;
477    case ID_VEC3D_ARRAY:
478        {
479            osg::Vec3dArray* va = new osg::Vec3dArray;
480            readArrayImplementation( va, 3, DOUBLE_SIZE );
481            array = va;
482        }
483        break;
484    case ID_VEC4D_ARRAY:
485        {
486            osg::Vec4dArray* va = new osg::Vec4dArray;
487            readArrayImplementation( va, 4, DOUBLE_SIZE );
488            array = va;
489        }
490        break;
491    default:
492        throwException( "InputStream::readArray(): Unsupported array type." );
493    }
494
495    if ( getException() ) return NULL;
496    _arrayMap[id] = array;
497
498    return array.release();
499}
500
501osg::PrimitiveSet* InputStream::readPrimitiveSet()
502{
503    osg::ref_ptr<osg::PrimitiveSet> primitive = NULL;
504
505    DEF_MAPPEE(PrimitiveType, type);
506    DEF_MAPPEE(PrimitiveType, mode);
507    unsigned int numInstances = 0u;
508    *this >> type >> mode;
509    if ( _fileVersion>96 )
510    {
511        *this >> numInstances;
512    }
513
514    switch ( type.get() )
515    {
516    case ID_DRAWARRAYS:
517        {
518            int first = 0, count = 0;
519            *this >> first >> count;
520            osg::DrawArrays* da = new osg::DrawArrays( mode.get(), first, count );
521            primitive = da;
522            primitive->setNumInstances( numInstances );
523        }
524        break;
525    case ID_DRAWARRAY_LENGTH:
526        {
527            int first = 0, value = 0; unsigned int size = 0;
528            *this >> first >> size >> BEGIN_BRACKET;
529            osg::DrawArrayLengths* dl = new osg::DrawArrayLengths( mode.get(), first );
530            for ( unsigned int i=0; i<size; ++i )
531            {
532                *this >> value;
533                dl->push_back( value );
534            }
535            *this >> END_BRACKET;
536            primitive = dl;
537            primitive->setNumInstances( numInstances );
538        }
539        break;
540    case ID_DRAWELEMENTS_UBYTE:
541        {
542            osg::DrawElementsUByte* de = new osg::DrawElementsUByte( mode.get() );
543            unsigned int size = 0; unsigned char value = 0;
544            *this >> size >> BEGIN_BRACKET;
545            for ( unsigned int i=0; i<size; ++i )
546            {
547                *this >> value;
548                de->push_back( value );
549            }
550            *this >> END_BRACKET;
551            primitive = de;
552            primitive->setNumInstances( numInstances );
553        }
554        break;
555    case ID_DRAWELEMENTS_USHORT:
556        {
557            osg::DrawElementsUShort* de = new osg::DrawElementsUShort( mode.get() );
558            unsigned int size = 0; unsigned short value = 0;
559            *this >> size >> BEGIN_BRACKET;
560            for ( unsigned int i=0; i<size; ++i )
561            {
562                *this >> value;
563                de->push_back( value );
564            }
565            *this >> END_BRACKET;
566            primitive = de;
567            primitive->setNumInstances( numInstances );
568        }
569        break;
570    case ID_DRAWELEMENTS_UINT:
571        {
572            osg::DrawElementsUInt* de = new osg::DrawElementsUInt( mode.get() );
573            unsigned int size = 0, value = 0;
574            *this >> size >> BEGIN_BRACKET;
575            for ( unsigned int i=0; i<size; ++i )
576            {
577                *this >> value;
578                de->push_back( value );
579            }
580            *this >> END_BRACKET;
581            primitive = de;
582            primitive->setNumInstances( numInstances );
583        }
584        break;
585    default:
586        throwException( "InputStream::readPrimitiveSet(): Unsupported array type." );
587    }
588
589    if ( getException() ) return NULL;
590    return primitive.release();
591}
592
593osg::Image* InputStream::readImage(bool readFromExternal)
594{
595    std::string className = "osg::Image";
596    if ( _fileVersion>94 )  // ClassName property is only supported in 3.1.4 and higher
597        *this >> PROPERTY("ClassName") >> className;
598
599    unsigned int id = 0;
600    *this >> PROPERTY("UniqueID") >> id;
601    if ( getException() ) return NULL;
602
603    IdentifierMap::iterator itr = _identifierMap.find( id );
604    if ( itr!=_identifierMap.end() )
605    {
606        return static_cast<osg::Image*>( itr->second.get() );
607    }
608
609    std::string name;
610    int writeHint, decision = IMAGE_EXTERNAL;
611    *this >> PROPERTY("FileName"); readWrappedString(name);
612    *this >> PROPERTY("WriteHint") >> writeHint >> decision;
613    if ( getException() ) return NULL;
614
615    osg::ref_ptr<osg::Image> image = NULL;
616    switch ( decision )
617    {
618    case IMAGE_INLINE_DATA:
619        if ( isBinary() )
620        {
621            // _origin, _s & _t & _r, _internalTextureFormat
622            int origin, s, t, r, internalFormat;
623            *this >> origin >> s >> t >> r >> internalFormat;
624
625            // _pixelFormat, _dataType, _packing, _allocationMode
626            int pixelFormat, dataType, packing, mode;
627            *this >> pixelFormat >> dataType >> packing >> mode;
628
629            // _data
630            unsigned int size = 0; *this >> size;
631            if ( size )
632            {
633                char* data = new char[size];
634                if ( !data )
635                    throwException( "InputStream::readImage() Out of memory." );
636                if ( getException() ) return NULL;
637
638                readCharArray( data, size );
639                image = new osg::Image;
640                image->setOrigin( (osg::Image::Origin)origin );
641                image->setImage( s, t, r, internalFormat, pixelFormat, dataType,
642                    (unsigned char*)data, (osg::Image::AllocationMode)mode, packing );
643            }
644
645            // _mipmapData
646            unsigned int levelSize = readSize();
647            osg::Image::MipmapDataType levels(levelSize);
648            for ( unsigned int i=0; i<levelSize; ++i )
649            {
650                *this >> levels[i];
651            }
652            if ( image && levelSize>0 )
653                image->setMipmapLevels( levels );
654            readFromExternal = false;
655        }
656        break;
657    case IMAGE_INLINE_FILE:
658        if ( isBinary() )
659        {
660            unsigned int size = readSize();
661            if ( size>0 )
662            {
663                char* data = new char[size];
664                if ( !data )
665                {
666                    throwException( "InputStream::readImage(): Out of memory." );
667                    if ( getException() ) return NULL;
668                }
669                readCharArray( data, size );
670
671                std::string ext = osgDB::getFileExtension( name );
672                osgDB::ReaderWriter* reader =
673                    osgDB::Registry::instance()->getReaderWriterForExtension( ext );
674                if ( reader )
675                {
676                    std::stringstream inputStream;
677                    inputStream.write( data, size );
678
679                    osgDB::ReaderWriter::ReadResult rr = reader->readImage( inputStream );
680                    if ( rr.validImage() )
681                        image = rr.takeImage();
682                    else
683                    {
684                        OSG_WARN << "InputStream::readImage(): "
685                                               << rr.message() << std::endl;
686                    }
687                }
688                else
689                {
690                    OSG_WARN << "InputStream::readImage(): Unable to find a plugin for "
691                                           << ext << std::endl;
692                }
693                delete[] data;
694            }
695            readFromExternal = false;
696        }
697        break;
698    case IMAGE_EXTERNAL: case IMAGE_WRITE_OUT:
699        break;
700    default:
701        break;
702    }
703
704    if ( readFromExternal && !name.empty() )
705    {
706        image = osgDB::readImageFile( name, getOptions() );
707        if ( !image && _forceReadingImage ) image = new osg::Image;
708    }
709
710    image = static_cast<osg::Image*>( readObjectFields(className, id, image.get()) );
711    if ( image.valid() )
712    {
713        image->setFileName( name );
714        image->setWriteHint( (osg::Image::WriteHint)writeHint );
715    }
716    return image.release();
717}
718
719osg::Object* InputStream::readObject( osg::Object* existingObj )
720{
721    std::string className;
722    unsigned int id = 0;
723    *this >> className >> BEGIN_BRACKET >> PROPERTY("UniqueID") >> id;
724    if ( getException() ) return NULL;
725
726    IdentifierMap::iterator itr = _identifierMap.find( id );
727    if ( itr!=_identifierMap.end() )
728    {
729        advanceToCurrentEndBracket();
730        return itr->second.get();
731    }
732
733    osg::ref_ptr<osg::Object> obj = readObjectFields( className, id, existingObj );
734
735    advanceToCurrentEndBracket();
736
737    return obj.release();
738}
739
740osg::Object* InputStream::readObjectFields( const std::string& className, unsigned int id, osg::Object* existingObj )
741{
742    ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( className );
743    if ( !wrapper )
744    {
745        OSG_WARN << "InputStream::readObject(): Unsupported wrapper class "
746                               << className << std::endl;
747        return NULL;
748    }
749
750    osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->getProto()->cloneType();
751    _identifierMap[id] = obj;
752    if ( obj.valid() )
753    {
754        const StringList& associates = wrapper->getAssociates();
755        for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
756        {
757            ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr);
758            if ( !assocWrapper )
759            {
760                OSG_WARN << "InputStream::readObject(): Unsupported associated class "
761                                       << *itr << std::endl;
762                continue;
763            }
764            _fields.push_back( assocWrapper->getName() );
765            assocWrapper->read( *this, *obj );
766            if ( getException() ) return NULL;
767
768            _fields.pop_back();
769        }
770    }
771    return obj.release();
772}
773
774void InputStream::readSchema( std::istream& fin )
775{
776    // Read from external ascii stream
777    std::string line;
778    while ( std::getline(fin, line) )
779    {
780        if ( line[0]=='#' ) continue// Comment
781
782        StringList keyAndValue;
783        split( line, keyAndValue, '=' );
784        if ( keyAndValue.size()<2 ) continue;
785
786        setWrapperSchema( osgDB::trimEnclosingSpaces(keyAndValue[0]),
787                          osgDB::trimEnclosingSpaces(keyAndValue[1]) );
788    }
789}
790
791InputStream::ReadType InputStream::start( InputIterator* inIterator )
792{
793    _fields.clear();
794    _fields.push_back( "Start" );
795
796    ReadType type = READ_UNKNOWN;
797    _in = inIterator;
798    if ( !_in )
799        throwException( "InputStream: Null stream specified." );
800    if ( getException() ) return type;
801
802    _in->setInputStream(this);
803
804    // Check OSG header information
805    unsigned int version = 0;
806    if ( isBinary() )
807    {
808        unsigned int typeValue;
809        *this >> typeValue >> version;
810        type = static_cast<ReadType>(typeValue);
811
812        unsigned int attributes; *this >> attributes;
813        if ( attributes&0x4 ) inIterator->setSupportBinaryBrackets( true );
814        if ( attributes&0x2 ) _useSchemaData = true;
815
816        // Record custom domains
817        if ( attributes&0x1 )
818        {
819            unsigned int numDomains; *this >> numDomains;
820            for ( unsigned int i=0; i<numDomains; ++i )
821            {
822                std::string domainName; *this >> domainName;
823                int domainVersion; *this >> domainVersion;
824                _domainVersionMap[domainName] = domainVersion;
825            }
826        }
827    }
828    if ( !isBinary() )
829    {
830        std::string typeString; *this >> typeString;
831        if ( typeString=="Scene" ) type = READ_SCENE;
832        else if ( typeString=="Image" ) type = READ_IMAGE;
833        else if ( typeString=="Object" ) type = READ_OBJECT;
834
835        std::string osgName, osgVersion;
836        *this >> PROPERTY("#Version") >> version;
837        *this >> PROPERTY("#Generator") >> osgName >> osgVersion;
838
839        while ( matchString("#CustomDomain") )
840        {
841            std::string domainName; *this >> domainName;
842            int domainVersion; *this >> domainVersion;
843            _domainVersionMap[domainName] = domainVersion;
844        }
845    }
846
847    // Record file version for back-compatibility checking of wrappers
848    _fileVersion = version;
849    _fields.pop_back();
850    return type;
851}
852
853void InputStream::decompress()
854{
855    if ( !isBinary() ) return;
856    _fields.clear();
857
858    std::string compressorName; *this >> compressorName;
859    if ( compressorName!="0" )
860    {
861        std::string data;
862        _fields.push_back( "Decompression" );
863
864        BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName);
865        if ( !compressor )
866        {
867            OSG_WARN << "InputStream::decompress(): No such compressor "
868                                   << compressorName << std::endl;
869        }
870
871        if ( !compressor->decompress(*(_in->getStream()), data) )
872            throwException( "InputStream: Failed to decompress stream." );
873        if ( getException() ) return;
874
875        _dataDecompress = new std::stringstream(data);
876        _in->setStream( _dataDecompress );
877        _fields.pop_back();
878    }
879
880    if ( _useSchemaData )
881    {
882        _fields.push_back( "SchemaData" );
883        std::string schemaSource; *this >> schemaSource;
884        std::istringstream iss( schemaSource );
885        readSchema( iss );
886        _fields.pop_back();
887    }
888}
889
890// PROTECTED METHODS
891
892void InputStream::setWrapperSchema( const std::string& name, const std::string& properties )
893{
894    ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(name);
895    if ( !wrapper )
896    {
897        OSG_WARN << "InputStream::setSchema(): Unsupported wrapper class "
898                               << name << std::endl;
899        return;
900    }
901
902    StringList schema, methods, keyAndValue;
903    std::vector<int> types;
904    split( properties, schema );
905    for ( StringList::iterator itr=schema.begin(); itr!=schema.end(); ++itr )
906    {
907        split( *itr, keyAndValue, ':' );
908        if ( keyAndValue.size()>1 )
909        {
910            methods.push_back( keyAndValue.front() );
911            types.push_back( atoi(keyAndValue.back().c_str()) );
912        }
913        else
914        {
915            methods.push_back( *itr );
916            types.push_back( 0 );
917        }
918        keyAndValue.clear();
919    }
920    wrapper->readSchema( methods, types );
921}
922
923void InputStream::resetSchema()
924{
925    const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap();
926    for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin();
927          itr!=wrappers.end(); ++itr )
928    {
929        ObjectWrapper* wrapper = itr->second.get();
930        wrapper->resetSchema();
931    }
932}
933
934template<typename T>
935void InputStream::readArrayImplementation( T* a, unsigned int numComponentsPerElements, unsigned int componentSizeInBytes )
936{
937    int size = 0;
938    *this >> size >> BEGIN_BRACKET;
939    if ( size )
940    {
941        a->resize( size );
942        if ( isBinary() )
943        {
944            readComponentArray( (char*)&((*a)[0]), size, numComponentsPerElements, componentSizeInBytes );
945            checkStream();
946        }
947        else
948        {
949            for ( int i=0; i<size; ++i )
950                *this >> (*a)[i];
951        }
952    }
953    *this >> END_BRACKET;
954}
Note: See TracBrowser for help on using the browser.