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

Revision 10986, 20.9 kB (checked in by robert, 4 years ago)

From Wang Rui, refactored the InputStream/OutputStream? operations so that the binar/ascii foramts are implemented via subclasses.

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:   _byteSwap(0), _useFloatMatrix(false),
28    _in(0)
29{
30    if ( !options ) return;
31   
32    std::string schema;
33    StringList optionList;
34    split( options->getOptionString(), optionList );
35    for ( StringList::iterator itr=optionList.begin(); itr!=optionList.end(); ++itr )
36    {
37        const std::string& option = *itr;
38        if ( option=="Ascii" )
39        {
40            // Omit this
41        }
42        else
43        {
44            StringList keyAndValues;
45            split( option, keyAndValues, '=' );
46            if ( keyAndValues.size()<2 ) continue;
47           
48            if ( keyAndValues[0]=="SchemaFile" )
49            {
50                schema = keyAndValues[1];
51                if ( s_lastSchema!=schema )
52                {
53                    osgDB::ifstream schemaStream( schema.c_str(), std::ios::in );
54                    if ( !schemaStream.fail() ) readSchema( schemaStream );
55                    schemaStream.close();
56                    s_lastSchema = schema;
57                }
58            }
59            else
60                osg::notify(osg::WARN) << "InputStream: Unknown option " << option << std::endl;
61        }
62    }
63    if ( schema.empty() )
64    {
65        resetSchema();
66        s_lastSchema.clear();
67    }
68}
69
70InputStream::~InputStream()
71{
72}
73
74InputStream& InputStream::operator>>( osg::Vec2b& v )
75{
76    char x, y; *this >> x >> y;
77    v.set( x, y );
78    return *this;
79}
80
81InputStream& InputStream::operator>>( osg::Vec3b& v )
82{
83    char x, y, z; *this >> x >> y >> z;
84    v.set( x, y, z );
85    return *this;
86}
87
88InputStream& InputStream::operator>>( osg::Vec4b& v )
89{
90    char x, y, z, w; *this >> x >> y >> z >> w;
91    v.set( x, y, z, w );
92    return *this;
93}
94
95InputStream& InputStream::operator>>( osg::Vec4ub& v )
96{
97    char r, g, b, a; *this >> r >> g >> b >> a;
98    v.set( r, g, b, a );
99    return *this;
100}
101
102InputStream& InputStream::operator>>( osg::Vec2s& v )
103{ *this >> v.x() >> v.y(); return *this; }
104
105InputStream& InputStream::operator>>( osg::Vec3s& v )
106{ *this >> v.x() >> v.y() >> v.z(); return *this; }
107
108InputStream& InputStream::operator>>( osg::Vec4s& v )
109{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
110
111InputStream& InputStream::operator>>( osg::Vec2f& v )
112{ *this >> v.x() >> v.y(); return *this; }
113
114InputStream& InputStream::operator>>( osg::Vec3f& v )
115{ *this >> v.x() >> v.y() >> v.z(); return *this; }
116
117InputStream& InputStream::operator>>( osg::Vec4f& v )
118{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
119
120InputStream& InputStream::operator>>( osg::Vec2d& v )
121{ *this >> v.x() >> v.y(); return *this; }
122
123InputStream& InputStream::operator>>( osg::Vec3d& v )
124{ *this >> v.x() >> v.y() >> v.z(); return *this; }
125
126InputStream& InputStream::operator>>( osg::Vec4d& v )
127{ *this >> v.x() >> v.y() >> v.z() >> v.w(); return *this; }
128
129InputStream& InputStream::operator>>( osg::Quat& q )
130{ *this >> q.x() >> q.y() >> q.z() >> q.w(); return *this; }
131
132InputStream& InputStream::operator>>( osg::Plane& p )
133{
134    double p0, p1, p2, p3; *this >> p0 >> p1 >> p2 >> p3;
135    p.set( p0, p1, p2, p3 ); return *this;
136}
137
138InputStream& InputStream::operator>>( osg::Matrixf& mat )
139{
140    *this >> PROPERTY("Matrixf") >> BEGIN_BRACKET;
141    for ( int r=0; r<4; ++r )
142    {
143        *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
144    }
145    *this >> END_BRACKET;
146    return *this;
147}
148
149InputStream& InputStream::operator>>( osg::Matrixd& mat )
150{
151    *this >> PROPERTY("Matrixd") >> BEGIN_BRACKET;
152    for ( int r=0; r<4; ++r )
153    {
154        *this >> mat(r, 0) >> mat(r, 1) >> mat(r, 2) >> mat(r, 3);
155    }
156    *this >> END_BRACKET;
157    return *this;
158}
159
160osg::Array* InputStream::readArray()
161{
162    osg::ref_ptr<osg::Array> array = NULL;
163   
164    unsigned int id = 0;
165    *this >> PROPERTY("ArrayID") >> id;
166   
167    ArrayMap::iterator itr = _arrayMap.find( id );
168    if ( itr!=_arrayMap.end() ) return itr->second.get();
169   
170    DEF_MAPPEE(ArrayType, type);
171    *this >> type;
172    switch ( type.get() )
173    {
174    case ID_BYTE_ARRAY:
175        {
176            osg::ByteArray* ba = new osg::ByteArray;
177            readArrayImplementation( ba, CHAR_SIZE, true );
178            array = ba;
179        }
180        break;
181    case ID_UBYTE_ARRAY:
182        {
183            osg::UByteArray* uba = new osg::UByteArray;
184            readArrayImplementation( uba, CHAR_SIZE, true );
185            array = uba;
186        }
187        break;
188    case ID_SHORT_ARRAY:
189        {
190            osg::ShortArray* sa = new osg::ShortArray;
191            readArrayImplementation( sa, SHORT_SIZE, true );
192            array = sa;
193        }
194        break;
195    case ID_USHORT_ARRAY:
196        {
197            osg::UShortArray* usa = new osg::UShortArray;
198            readArrayImplementation( usa, SHORT_SIZE, true );
199            array = usa;
200        }
201        break;
202    case ID_INT_ARRAY:
203        {
204            osg::IntArray* ia = new osg::IntArray;
205            readArrayImplementation( ia, INT_SIZE, true );
206            array = ia;
207        }
208        break;
209    case ID_UINT_ARRAY:
210        {
211            osg::UIntArray* uia = new osg::UIntArray;
212            readArrayImplementation( uia, INT_SIZE, true );
213            array = uia;
214        }
215        break;
216    case ID_FLOAT_ARRAY:
217        {
218            osg::FloatArray* fa = new osg::FloatArray;
219            readArrayImplementation( fa, FLOAT_SIZE, true );
220            array = fa;
221        }
222        break;
223    case ID_DOUBLE_ARRAY:
224        {
225            osg::DoubleArray* da = new osg::DoubleArray;
226            readArrayImplementation( da, DOUBLE_SIZE, true );
227            array = da;
228        }
229        break;
230    case ID_VEC2B_ARRAY:
231        {
232            osg::Vec2bArray* va = new osg::Vec2bArray;
233            readArrayImplementation( va, 2*CHAR_SIZE );
234            array = va;
235        }
236        break;
237    case ID_VEC3B_ARRAY:
238        {
239            osg::Vec3bArray* va = new osg::Vec3bArray;
240            readArrayImplementation( va, 3*CHAR_SIZE );
241            array = va;
242        }
243        break;
244    case ID_VEC4B_ARRAY:
245        {
246            osg::Vec4bArray* va = new osg::Vec4bArray;
247            readArrayImplementation( va, 4*CHAR_SIZE );
248            array = va;
249        }
250        break;
251    case ID_VEC4UB_ARRAY:
252        {
253            osg::Vec4ubArray* va = new osg::Vec4ubArray;
254            readArrayImplementation( va, 4*CHAR_SIZE );
255            array = va;
256        }
257        break;
258    case ID_VEC2S_ARRAY:
259        {
260            osg::Vec2sArray* va = new osg::Vec2sArray;
261            readArrayImplementation( va, 2*SHORT_SIZE );
262            array = va;
263        }
264        break;
265    case ID_VEC3S_ARRAY:
266        {
267            osg::Vec3sArray* va = new osg::Vec3sArray;
268            readArrayImplementation( va, 3*SHORT_SIZE );
269            array = va;
270        }
271        break;
272    case ID_VEC4S_ARRAY:
273        {
274            osg::Vec4sArray* va = new osg::Vec4sArray;
275            readArrayImplementation( va, 4*SHORT_SIZE );
276            array = va;
277        }
278        break;
279    case ID_VEC2_ARRAY:
280        {
281            osg::Vec2Array* va = new osg::Vec2Array;
282            readArrayImplementation( va, 2*FLOAT_SIZE );
283            array = va;
284        }
285        break;
286    case ID_VEC3_ARRAY:
287        {
288            osg::Vec3Array* va = new osg::Vec3Array;
289            readArrayImplementation( va, 3*FLOAT_SIZE );
290            array = va;
291        }
292        break;
293    case ID_VEC4_ARRAY:
294        {
295            osg::Vec4Array* va = new osg::Vec4Array;
296            readArrayImplementation( va, 4*FLOAT_SIZE );
297            array = va;
298        }
299        break;
300    case ID_VEC2D_ARRAY:
301        {
302            osg::Vec2dArray* va = new osg::Vec2dArray;
303            readArrayImplementation( va, 2*DOUBLE_SIZE );
304            array = va;
305        }
306        break;
307    case ID_VEC3D_ARRAY:
308        {
309            osg::Vec3dArray* va = new osg::Vec3dArray;
310            readArrayImplementation( va, 3*DOUBLE_SIZE );
311            array = va;
312        }
313        break;
314    case ID_VEC4D_ARRAY:
315        {
316            osg::Vec4dArray* va = new osg::Vec4dArray;
317            readArrayImplementation( va, 4*DOUBLE_SIZE );
318            array = va;
319        }
320        break;
321    default:
322        throw InputException(_currentField, "InputStream::readArray(): Unsupported array type.");
323    }
324   
325    _arrayMap[id] = array;
326    return array.release();
327}
328
329osg::PrimitiveSet* InputStream::readPrimitiveSet()
330{
331    osg::ref_ptr<osg::PrimitiveSet> primitive = NULL;
332   
333    DEF_MAPPEE(PrimitiveType, type);
334    DEF_MAPPEE(PrimitiveType, mode);
335    *this >> type >> mode;
336   
337    switch ( type.get() )
338    {
339    case ID_DRAWARRAYS:
340        {
341            int first = 0, count = 0;
342            *this >> first >> count;
343            osg::DrawArrays* da = new osg::DrawArrays( mode.get(), first, count );
344            primitive = da;
345        }
346        break;
347    case ID_DRAWARRAY_LENGTH:
348        {
349            int first = 0, value = 0; unsigned int size = 0;
350            *this >> first >> size >> BEGIN_BRACKET;
351            osg::DrawArrayLengths* dl = new osg::DrawArrayLengths( mode.get(), first );
352            for ( unsigned int i=0; i<size; ++i )
353            {
354                *this >> value;
355                dl->push_back( value );
356            }
357            *this >> END_BRACKET;
358            primitive = dl;
359        }
360        break;
361    case ID_DRAWELEMENTS_UBYTE:
362        {
363            osg::DrawElementsUByte* de = new osg::DrawElementsUByte( mode.get() );
364            unsigned int size = 0; unsigned char value = 0;
365            *this >> size >> BEGIN_BRACKET;
366            for ( unsigned int i=0; i<size; ++i )
367            {
368                *this >> value;
369                de->push_back( value );
370            }
371            *this >> END_BRACKET;
372            primitive = de;
373        }
374        break;
375    case ID_DRAWELEMENTS_USHORT:
376        {
377            osg::DrawElementsUShort* de = new osg::DrawElementsUShort( mode.get() );
378            unsigned int size = 0; unsigned short value = 0;
379            *this >> size >> BEGIN_BRACKET;
380            for ( unsigned int i=0; i<size; ++i )
381            {
382                *this >> value;
383                de->push_back( value );
384            }
385            *this >> END_BRACKET;
386            primitive = de;
387        }
388        break;
389    case ID_DRAWELEMENTS_UINT:
390        {
391            osg::DrawElementsUInt* de = new osg::DrawElementsUInt( mode.get() );
392            unsigned int size = 0, value = 0;
393            *this >> size >> BEGIN_BRACKET;
394            for ( unsigned int i=0; i<size; ++i )
395            {
396                *this >> value;
397                de->push_back( value );
398            }
399            *this >> END_BRACKET;
400            primitive = de;
401        }
402        break;
403    default:
404        throw InputException(_currentField, "InputStream::readPrimitiveSet(): Unsupported array type.");
405    }
406    return primitive.release();
407}
408
409osg::Image* InputStream::readImage()
410{
411    std::string name;
412    int writeHint, decision = IMAGE_EXTERNAL;
413    *this >> PROPERTY("FileName"); readWrappedString(name);
414    *this >> PROPERTY("WriteHint") >> writeHint >> decision;
415   
416    osg::ref_ptr<osg::Image> image = NULL;
417    bool readFromExternal = true;
418    switch ( decision )
419    {
420    case IMAGE_INLINE_DATA:
421        if ( isBinary() )
422        {
423            image = new osg::Image;
424           
425            // _origin, _s & _t & _r, _internalTextureFormat
426            int origin, s, t, r, internalFormat;
427            *this >> origin >> s >> t >> r >> internalFormat;
428           
429            // _pixelFormat, _dataType, _packing, _allocationMode
430            int pixelFormat, dataType, packing, mode;
431            *this >> pixelFormat >> dataType >> packing >> mode;
432           
433            // _data
434            unsigned int size = 0; *this >> size;
435            if ( size )
436            {
437                char* data = new char[size];
438                if ( !data )
439                    throw InputException(_currentField, "InputStream::readImage() Out of memory.");
440                readCharArray( data, size );
441                image->setOrigin( (osg::Image::Origin)origin );
442                image->setImage( s, t, r, internalFormat, pixelFormat, dataType,
443                    (unsigned char*)data, (osg::Image::AllocationMode)mode, packing );
444            }
445
446            // _mipmapData
447            unsigned int levelSize = 0; *this >> levelSize;
448            osg::Image::MipmapDataType levels(levelSize);
449            for ( unsigned int i=0; i<levelSize; ++i )
450            {
451                *this >> levels[i];
452            }
453            if ( levelSize>0 )
454                image->setMipmapLevels( levels );
455            readFromExternal = false;
456        }
457        break;
458    case IMAGE_INLINE_FILE:
459        if ( isBinary() )
460        {
461            unsigned int size = 0; *this >> size;
462            if ( size>0 )
463            {
464                char* data = new char[size];
465                if ( !data )
466                    throw InputException(_currentField, "InputStream::readImage(): Out of memory.");
467                readCharArray( data, size );
468               
469                std::string ext = osgDB::getFileExtension( name );
470                osgDB::ReaderWriter* reader =
471                    osgDB::Registry::instance()->getReaderWriterForExtension( ext );
472                if ( reader )
473                {
474                    std::stringstream inputStream;
475                    inputStream.write( data, size );
476                   
477                    osgDB::ReaderWriter::ReadResult rr = reader->readImage( inputStream );
478                    if ( rr.validImage() )
479                        image = rr.takeImage();
480                    else
481                    {
482                        osg::notify(osg::WARN) << "InputStream::readImage(): "
483                                               << rr.message() << std::endl;
484                    }
485                }
486                else
487                {
488                    osg::notify(osg::WARN) << "InputStream::readImage(): Unable to find a plugin for "
489                                           << ext << std::endl;
490                }
491                delete[] data;
492            }
493            readFromExternal = false;
494        }
495        break;
496    case IMAGE_EXTERNAL: case IMAGE_WRITE_OUT:
497        break;
498    default:
499        break;
500    }
501   
502    if ( readFromExternal )
503        image = osgDB::readImageFile( name );
504    if ( image.valid() )
505    {
506        image->setFileName( name );
507        image->setWriteHint( (osg::Image::WriteHint)writeHint );
508    }
509   
510    image = static_cast<osg::Image*>( readObject(image.get()) );
511    return image.release();
512}
513
514osg::Object* InputStream::readObject( osg::Object* existingObj )
515{
516    std::string className;
517    unsigned int id = 0;
518    *this >> className >> BEGIN_BRACKET >> PROPERTY("UniqueID") >> id;
519   
520    IdentifierMap::iterator itr = _identifierMap.find( id );
521    if ( itr!=_identifierMap.end() )
522    {
523        advanceToCurrentEndBracket();
524        return itr->second.get();
525    }
526   
527    ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( className );
528    if ( !wrapper )
529    {
530        osg::notify(osg::WARN) << "InputStream::readObject(): Unsupported wrapper class "
531                               << className << std::endl;
532        advanceToCurrentEndBracket();
533        return NULL;
534    }
535    osg::ref_ptr<osg::Object> obj = existingObj ? existingObj : wrapper->getProto()->cloneType();
536    if ( obj.valid() )
537    {
538        _identifierMap[id] = obj;
539       
540        const StringList& associates = wrapper->getAssociates();
541        for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
542        {
543            ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr);
544            if ( !assocWrapper )
545            {
546                osg::notify(osg::WARN) << "InputStream::readObject(): Unsupported associated class "
547                                       << *itr << std::endl;
548                continue;
549            }
550           
551            _currentField = assocWrapper->getName();
552            assocWrapper->read( *this, *obj );
553        }
554    }
555    advanceToCurrentEndBracket();
556    return obj.release();
557}
558
559void InputStream::readSchema( std::istream& fin )
560{
561    // Read from external ascii stream
562    std::string line;
563    while ( std::getline(fin, line) )
564    {
565        if ( line[0]=='#' ) continue// Comment
566       
567        StringList keyAndValue;
568        split( line, keyAndValue, '=' );
569        if ( keyAndValue.size()<2 ) continue;
570       
571        setWrapperSchema( osgDB::trimEnclosingSpaces(keyAndValue[0]),
572                          osgDB::trimEnclosingSpaces(keyAndValue[1]) );
573    }
574}
575
576InputStream::ReadType InputStream::start( InputIterator* inIterator )
577{
578    ReadType type = READ_UNKNOWN;
579    _currentField = "Header";
580    _in = inIterator;
581    if ( !_in )
582        throw InputException(_currentField, "InputStream: Null stream specified.");
583   
584    // Check OSG header information
585    unsigned int version = 0;
586    if ( isBinary() )
587    {
588        unsigned int typeValue;
589        *this >> typeValue >> version;
590        type = static_cast<ReadType>(typeValue);
591       
592        unsigned int matrixValueType; *this >> matrixValueType;
593        if ( matrixValueType==0 ) _useFloatMatrix = true;
594        else _useFloatMatrix = false;
595    }
596    if ( !isBinary() )
597    {
598        DEF_PROPERTY("#Ascii", header); *this >> header;
599        if ( header._name!="#Ascii" ) return READ_UNKNOWN;
600       
601        std::string typeString; *this >> typeString;
602        if ( typeString=="Scene" ) type = READ_SCENE;
603        else if ( typeString=="Image" ) type = READ_IMAGE;
604       
605        std::string osgName, osgVersion;
606        *this >> PROPERTY("#Version") >> version;
607        *this >> PROPERTY("#Generator") >> osgName >> osgVersion;
608    }
609   
610    // Check file version
611    if ( version!=PLUGIN_VERSION )
612    {
613        osg::notify(osg::WARN) << "InputStream: Input data version " << version
614                               << " may be incompatible with current reader version "
615                               << PLUGIN_VERSION << std::endl;
616    }
617    return type;
618}
619
620void InputStream::decompress()
621{
622    _currentField = "Decompression";
623    if ( !isBinary() ) return;
624   
625    std::string compressorName; *this >> compressorName;
626    if ( compressorName=="0" ) return;
627   
628    BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName);
629    if ( !compressor )
630    {
631        osg::notify(osg::WARN) << "InputStream::decompress(): No such compressor "
632                               << compressorName << std::endl;
633    }
634   
635    std::string data;
636    if ( !compressor->decompress(*(_in->getStream()), data) )
637        throw InputException(_currentField, "InputStream: Failed to decompress stream.");
638    _in->setStream( new std::stringstream(data) );
639}
640
641// PROTECTED METHODS
642
643void InputStream::setWrapperSchema( const std::string& name, const std::string& properties )
644{
645    ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(name);
646    if ( !wrapper )
647    {
648        osg::notify(osg::WARN) << "InputStream::setSchema(): Unsupported wrapper class "
649                               << name << std::endl;
650        return;
651    }
652   
653    StringList schema;
654    split( properties, schema );
655    wrapper->readSchema( schema );
656}
657
658void InputStream::resetSchema()
659{
660    const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap();
661    for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin();
662          itr!=wrappers.end(); ++itr )
663    {
664        ObjectWrapper* wrapper = itr->second.get();
665        wrapper->resetSchema();
666    }
667}
668
669template<typename T>
670void InputStream::readArrayImplementation( T* a, int readSize, bool useByteSwap )
671{
672    int size = 0;
673    *this >> size >> BEGIN_BRACKET;
674    if ( size )
675    {
676        a->resize( size );
677        if ( isBinary() )
678        {
679            _in->getStream()->read( (char*)&((*a)[0]), readSize*size ); checkStream();
680            if ( useByteSwap && _byteSwap )
681            {
682                for ( int i=0; i<size; ++i )
683                    osg::swapBytes( (char*)&((*a)[i]), readSize );
684            }
685        }
686        else
687        {
688            for ( int i=0; i<size; ++i )
689                *this >> (*a)[i];
690        }
691    }
692    *this >> END_BRACKET;
693}
Note: See TracBrowser for help on using the browser.