root/OpenSceneGraph/trunk/src/osgDB/OutputStream.cpp @ 12896

Revision 12896, 24.4 kB (checked in by robert, 3 years ago)

Added handling of an empty filename when writing out an image file.

  • 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/Version>
16#include <osg/Notify>
17#include <osgDB/FileUtils>
18#include <osgDB/WriteFile>
19#include <osgDB/ObjectWrapper>
20#include <fstream>
21#include <sstream>
22
23using namespace osgDB;
24
25OutputStream::OutputStream( const osgDB::Options* options )
26:   _writeImageHint(WRITE_USE_IMAGE_HINT), _useSchemaData(false)
27{
28    if ( !options ) return;
29    _options = options;
30   
31    if ( options->getPluginStringData("SchemaData")=="true" )
32        _useSchemaData = true;
33    if ( !options->getPluginStringData("SchemaFile").empty() )
34        _schemaName = options->getPluginStringData("SchemaFile");
35    if ( !options->getPluginStringData("Compressor").empty() )
36        _compressorName = options->getPluginStringData("Compressor");
37    if ( !options->getPluginStringData("WriteImageHint").empty() )
38    {
39        std::string hintString = options->getPluginStringData("WriteImageHint");
40        if ( hintString=="IncludeData" ) _writeImageHint = WRITE_INLINE_DATA;
41        else if ( hintString=="IncludeFile" ) _writeImageHint = WRITE_INLINE_FILE;
42        else if ( hintString=="UseExternal" ) _writeImageHint = WRITE_USE_EXTERNAL;
43        else if ( hintString=="WriteOut" ) _writeImageHint = WRITE_EXTERNAL_FILE;
44    }
45}
46
47OutputStream::~OutputStream()
48{
49}
50
51OutputStream& OutputStream::operator<<( const osg::Vec2b& v )
52{ *this << v.x() << v.y(); return *this; }
53
54OutputStream& OutputStream::operator<<( const osg::Vec3b& v )
55{ *this << v.x() << v.y() << v.z(); return *this; }
56
57OutputStream& OutputStream::operator<<( const osg::Vec4b& v )
58{ *this << v.x() << v.y() << v.z() << v.w(); return *this; }
59
60OutputStream& OutputStream::operator<<( const osg::Vec4ub& v )
61{ *this << v.r() << v.g() << v.b() << v.a(); return *this; }
62
63OutputStream& OutputStream::operator<<( const osg::Vec2s& v )
64{ *this << v.x() << v.y(); return *this; }
65
66OutputStream& OutputStream::operator<<( const osg::Vec3s& v )
67{ *this << v.x() << v.y() << v.z(); return *this; }
68
69OutputStream& OutputStream::operator<<( const osg::Vec4s& v )
70{ *this << v.x() << v.y() << v.z() << v.w(); return *this; }
71
72OutputStream& OutputStream::operator<<( const osg::Vec2f& v )
73{ *this << v.x() << v.y(); return *this; }
74
75OutputStream& OutputStream::operator<<( const osg::Vec3f& v )
76{ *this << v.x() << v.y() << v.z(); return *this; }
77
78OutputStream& OutputStream::operator<<( const osg::Vec4f& v )
79{ *this << v.x() << v.y() << v.z() << v.w(); return *this; }
80
81OutputStream& OutputStream::operator<<( const osg::Vec2d& v )
82{ *this << v.x() << v.y(); return *this; }
83
84OutputStream& OutputStream::operator<<( const osg::Vec3d& v )
85{ *this << v.x() << v.y() << v.z(); return *this; }
86
87OutputStream& OutputStream::operator<<( const osg::Vec4d& v )
88{ *this << v.x() << v.y() << v.z() << v.w(); return *this; }
89
90OutputStream& OutputStream::operator<<( const osg::Quat& q )
91{ *this << q.x() << q.y() << q.z() << q.w(); return *this; }
92
93OutputStream& OutputStream::operator<<( const osg::Plane& p )
94{ *this << (double)p[0] << (double)p[1] << (double)p[2] << (double)p[3]; return *this; }
95
96
97#if 0
98OutputStream& OutputStream::operator<<( const osg::Matrixf& mat )
99{
100    *this << PROPERTY("Matrixf")<<BEGIN_BRACKET << std::endl;
101    for ( int r=0; r<4; ++r )
102    {
103        *this << mat(r, 0) << mat(r, 1)
104              << mat(r, 2) << mat(r, 3) << std::endl;
105    }
106    *this << END_BRACKET << std::endl;
107    return *this;
108}
109
110OutputStream& OutputStream::operator<<( const osg::Matrixd& mat )
111{
112    *this << PROPERTY("Matrixd")<<BEGIN_BRACKET << std::endl;
113    for ( int r=0; r<4; ++r )
114    {
115        *this << mat(r, 0) << mat(r, 1)
116              << mat(r, 2) << mat(r, 3) << std::endl;
117    }
118    *this << END_BRACKET << std::endl;
119    return *this;
120}
121#else
122OutputStream& OutputStream::operator<<( const osg::Matrixf& mat )
123{
124    *this << BEGIN_BRACKET << std::endl;
125    for ( int r=0; r<4; ++r )
126    {
127        *this << (double)mat(r, 0) << (double)mat(r, 1)
128              << (double)mat(r, 2) << (double)mat(r, 3) << std::endl;
129    }
130    *this << END_BRACKET << std::endl;
131    return *this;
132}
133
134OutputStream& OutputStream::operator<<( const osg::Matrixd& mat )
135{
136    *this << BEGIN_BRACKET << std::endl;
137    for ( int r=0; r<4; ++r )
138    {
139        *this << mat(r, 0) << mat(r, 1)
140              << mat(r, 2) << mat(r, 3) << std::endl;
141    }
142    *this << END_BRACKET << std::endl;
143    return *this;
144}
145#endif
146
147void OutputStream::writeArray( const osg::Array* a )
148{
149    if ( !a ) return;
150
151    bool newID = false;
152    unsigned int id = findOrCreateArrayID( a, newID );
153    *this << PROPERTY("ArrayID") << id;
154    if ( !newID )  // Shared array
155    {
156        *this << std::endl;
157        return;
158    }
159   
160    switch ( a->getType() )
161    {
162    case osg::Array::ByteArrayType:
163        *this << MAPPEE(ArrayType, ID_BYTE_ARRAY);
164        writeArrayImplementation( static_cast<const osg::ByteArray*>(a), a->getNumElements(), 4 );
165        break;
166    case osg::Array::UByteArrayType:
167        *this << MAPPEE(ArrayType, ID_UBYTE_ARRAY);
168        writeArrayImplementation( static_cast<const osg::UByteArray*>(a), a->getNumElements(), 4 );
169        break;
170    case osg::Array::ShortArrayType:
171        *this << MAPPEE(ArrayType, ID_SHORT_ARRAY);
172        writeArrayImplementation( static_cast<const osg::ShortArray*>(a), a->getNumElements(), 4 );
173        break;
174    case osg::Array::UShortArrayType:
175        *this << MAPPEE(ArrayType, ID_USHORT_ARRAY);
176        writeArrayImplementation( static_cast<const osg::UShortArray*>(a), a->getNumElements(), 4 );
177        break;
178    case osg::Array::IntArrayType:
179        *this << MAPPEE(ArrayType, ID_INT_ARRAY);
180        writeArrayImplementation( static_cast<const osg::IntArray*>(a), a->getNumElements(), 4 );
181        break;
182    case osg::Array::UIntArrayType:
183        *this << MAPPEE(ArrayType, ID_UINT_ARRAY);
184        writeArrayImplementation( static_cast<const osg::UIntArray*>(a), a->getNumElements(), 4 );
185        break;
186    case osg::Array::FloatArrayType:
187        *this << MAPPEE(ArrayType, ID_FLOAT_ARRAY);
188        writeArrayImplementation( static_cast<const osg::FloatArray*>(a), a->getNumElements(), 4 );
189        break;
190    case osg::Array::DoubleArrayType:
191        *this << MAPPEE(ArrayType, ID_DOUBLE_ARRAY);
192        writeArrayImplementation( static_cast<const osg::DoubleArray*>(a), a->getNumElements(), 4 );
193        break;
194    case osg::Array::Vec2bArrayType:
195        *this << MAPPEE(ArrayType, ID_VEC2B_ARRAY);
196        writeArrayImplementation( static_cast<const osg::Vec2bArray*>(a), a->getNumElements() );
197        break;
198    case osg::Array::Vec3bArrayType:
199        *this << MAPPEE(ArrayType, ID_VEC3B_ARRAY);
200        writeArrayImplementation( static_cast<const osg::Vec3bArray*>(a), a->getNumElements() );
201        break;
202    case osg::Array::Vec4bArrayType:
203        *this << MAPPEE(ArrayType, ID_VEC4B_ARRAY);
204        writeArrayImplementation( static_cast<const osg::Vec4bArray*>(a), a->getNumElements() );
205        break;
206    case osg::Array::Vec4ubArrayType:
207        *this << MAPPEE(ArrayType, ID_VEC4UB_ARRAY);
208        writeArrayImplementation( static_cast<const osg::Vec4ubArray*>(a), a->getNumElements() );
209        break;
210    case osg::Array::Vec2sArrayType:
211        *this << MAPPEE(ArrayType, ID_VEC2S_ARRAY);
212        writeArrayImplementation( static_cast<const osg::Vec2sArray*>(a), a->getNumElements() );
213        break;
214    case osg::Array::Vec3sArrayType:
215        *this << MAPPEE(ArrayType, ID_VEC3S_ARRAY);
216        writeArrayImplementation( static_cast<const osg::Vec3sArray*>(a), a->getNumElements() );
217        break;
218    case osg::Array::Vec4sArrayType:
219        *this << MAPPEE(ArrayType, ID_VEC4S_ARRAY);
220        writeArrayImplementation( static_cast<const osg::Vec4sArray*>(a), a->getNumElements() );
221        break;
222    case osg::Array::Vec2ArrayType:
223        *this << MAPPEE(ArrayType, ID_VEC2_ARRAY);
224        writeArrayImplementation( static_cast<const osg::Vec2Array*>(a), a->getNumElements() );
225        break;
226    case osg::Array::Vec3ArrayType:
227        *this << MAPPEE(ArrayType, ID_VEC3_ARRAY);
228        writeArrayImplementation( static_cast<const osg::Vec3Array*>(a), a->getNumElements() );
229        break;
230    case osg::Array::Vec4ArrayType:
231        *this << MAPPEE(ArrayType, ID_VEC4_ARRAY);
232        writeArrayImplementation( static_cast<const osg::Vec4Array*>(a), a->getNumElements() );
233        break;
234    case osg::Array::Vec2dArrayType:
235        *this << MAPPEE(ArrayType, ID_VEC2D_ARRAY);
236        writeArrayImplementation( static_cast<const osg::Vec2dArray*>(a), a->getNumElements() );
237        break;
238    case osg::Array::Vec3dArrayType:
239        *this << MAPPEE(ArrayType, ID_VEC3D_ARRAY);
240        writeArrayImplementation( static_cast<const osg::Vec3dArray*>(a), a->getNumElements() );
241        break;
242    case osg::Array::Vec4dArrayType:
243        *this << MAPPEE(ArrayType, ID_VEC4D_ARRAY);
244        writeArrayImplementation( static_cast<const osg::Vec4dArray*>(a), a->getNumElements() );
245        break;
246    default:
247        throwException( "OutputStream::writeArray(): Unsupported array type." );
248    }
249}
250
251void OutputStream::writePrimitiveSet( const osg::PrimitiveSet* p )
252{
253    if ( !p ) return;
254   
255    switch ( p->getType() )
256    {
257    case osg::PrimitiveSet::DrawArraysPrimitiveType:
258        *this << MAPPEE(PrimitiveType, ID_DRAWARRAYS);
259        {
260            const osg::DrawArrays* da = static_cast<const osg::DrawArrays*>(p);
261            *this << MAPPEE(PrimitiveType, da->getMode())
262                  << da->getFirst() << da->getCount() << std::endl;
263        }
264        break;
265    case osg::PrimitiveSet::DrawArrayLengthsPrimitiveType:
266        *this << MAPPEE(PrimitiveType, ID_DRAWARRAY_LENGTH);
267        {
268            const osg::DrawArrayLengths* dl = static_cast<const osg::DrawArrayLengths*>(p);
269            *this << MAPPEE(PrimitiveType, dl->getMode()) << dl->getFirst();
270            writeArrayImplementation( dl, dl->size(), 4 );
271        }
272        break;
273    case osg::PrimitiveSet::DrawElementsUBytePrimitiveType:
274        *this << MAPPEE(PrimitiveType, ID_DRAWELEMENTS_UBYTE);
275        {
276            const osg::DrawElementsUByte* de = static_cast<const osg::DrawElementsUByte*>(p);
277            *this << MAPPEE(PrimitiveType, de->getMode());
278            writeArrayImplementation( de, de->size(), 4 );
279        }
280        break;
281    case osg::PrimitiveSet::DrawElementsUShortPrimitiveType:
282        *this << MAPPEE(PrimitiveType, ID_DRAWELEMENTS_USHORT);
283        {
284            const osg::DrawElementsUShort* de = static_cast<const osg::DrawElementsUShort*>(p);
285            *this << MAPPEE(PrimitiveType, de->getMode());
286            writeArrayImplementation( de, de->size(), 4 );
287        }
288        break;
289    case osg::PrimitiveSet::DrawElementsUIntPrimitiveType:
290        *this << MAPPEE(PrimitiveType, ID_DRAWELEMENTS_UINT);
291        {
292            const osg::DrawElementsUInt* de = static_cast<const osg::DrawElementsUInt*>(p);
293            *this << MAPPEE(PrimitiveType, de->getMode());
294            writeArrayImplementation( de, de->size(), 4 );
295        }
296        break;
297    default:
298        throwException( "OutputStream::writePrimitiveSet(): Unsupported primitive type." );
299    }
300}
301
302void OutputStream::writeImage( const osg::Image* img )
303{
304    if ( !img ) return;
305
306    // std::string name = img->libraryName();
307    // name += std::string("::") + img->className();
308
309    bool newID = false;
310    unsigned int id = findOrCreateObjectID( img, newID );
311
312    // *this << name << BEGIN_BRACKET << std::endl;       // Write object name
313    *this << PROPERTY("UniqueID") << id << std::endl;  // Write image ID
314    if ( getException() ) return;
315
316    if (newID)
317    {
318        int decision = IMAGE_EXTERNAL;
319        switch ( _writeImageHint )
320        {
321        case OutputStream::WRITE_INLINE_DATA: decision = IMAGE_INLINE_DATA; break;
322        case OutputStream::WRITE_INLINE_FILE: decision = IMAGE_INLINE_FILE; break;
323        case OutputStream::WRITE_EXTERNAL_FILE: decision = IMAGE_WRITE_OUT; break;
324        case OutputStream::WRITE_USE_EXTERNAL: decision = IMAGE_EXTERNAL; break;
325        default:
326            if ( img->getWriteHint()==osg::Image::EXTERNAL_FILE )
327                decision = IMAGE_EXTERNAL;
328            else if ( isBinary() )
329                decision = IMAGE_INLINE_DATA;
330            break;
331        }
332
333
334        std::string imageFileName = img->getFileName();
335        if ( decision==IMAGE_WRITE_OUT || _writeImageHint==WRITE_EXTERNAL_FILE )
336        {
337            if (imageFileName.empty())
338            {
339                OSG_NOTICE<<"Empty Image::FileName resetting to image.dds"<<std::endl;
340                imageFileName = "image.dds";
341            }
342
343            bool result = osgDB::writeImageFile( *img, imageFileName );
344            OSG_NOTICE << "OutputStream::writeImage(): Write image data to external file " << imageFileName << std::endl;
345            if ( !result )
346            {
347                OSG_WARN << "OutputStream::writeImage(): Failed to write " << img->getFileName() << std::endl;
348            }
349        }
350
351        *this << PROPERTY("FileName"); writeWrappedString(imageFileName); *this << std::endl;
352        *this << PROPERTY("WriteHint") << (int)img->getWriteHint();
353        if ( getException() ) return;
354
355        *this << decision << std::endl;
356
357        switch ( decision )
358        {
359        case IMAGE_INLINE_DATA:
360            if ( isBinary() )
361            {
362                *this << img->getOrigin();  // _origin
363                *this << img->s() << img->t() << img->r(); // _s & _t & _r
364                *this << img->getInternalTextureFormat();  // _internalTextureFormat
365                *this << img->getPixelFormat();  // _pixelFormat
366                *this << img->getDataType();  // _dataType
367                *this << img->getPacking();  // _packing
368                *this << img->getAllocationMode();  // _allocationMode
369
370                // _data
371                unsigned int size = img->getTotalSizeInBytesIncludingMipmaps();
372                writeSize(size); writeCharArray( (char*)img->data(), size );
373
374                // _mipmapData
375                const osg::Image::MipmapDataType& levels = img->getMipmapLevels();
376                writeSize(levels.size());
377                for ( osg::Image::MipmapDataType::const_iterator itr=levels.begin();
378                    itr!=levels.end(); ++itr )
379                {
380                    *this << *itr;
381                }
382            }
383            break;
384        case IMAGE_INLINE_FILE:
385            if ( isBinary() )
386            {
387                std::string fullPath = osgDB::findDataFile( img->getFileName() );
388                std::ifstream infile( fullPath.c_str(), std::ios::in|std::ios::binary );
389                if ( infile )
390                {
391                    infile.seekg( 0, std::ios::end );
392                    unsigned int size = infile.tellg();
393                    writeSize(size);
394
395                    if ( size>0 )
396                    {
397                        char* data = new char[size];
398                        if ( !data )
399                        {
400                            throwException( "OutputStream::writeImage(): Out of memory." );
401                            if ( getException() ) return;
402                        }
403
404                        infile.seekg( 0, std::ios::beg );
405                        infile.read( data, size );
406                        writeCharArray( data, size );
407                        delete[] data;
408                    }
409                    infile.close();
410                }
411                else
412                {
413                    OSG_WARN << "OutputStream::writeImage(): Failed to open image file "
414                                        << img->getFileName() << std::endl;
415                    *this << (unsigned int)0;
416                }
417            }
418            break;
419        case IMAGE_EXTERNAL:
420            break;
421        default:
422            break;
423        }
424
425        writeObjectFields( img );
426    }
427
428    // *this << END_BRACKET << std::endl;
429}
430
431void OutputStream::writeObject( const osg::Object* obj )
432{
433    if ( !obj ) return;
434
435    std::string name = obj->libraryName();
436    name += std::string("::") + obj->className();
437
438    bool newID = false;
439    unsigned int id = findOrCreateObjectID( obj, newID );
440
441    *this << name << BEGIN_BRACKET << std::endl;       // Write object name
442    *this << PROPERTY("UniqueID") << id << std::endl;  // Write object ID
443    if ( getException() ) return;
444
445    if (newID)
446    {
447        writeObjectFields(obj);
448    }
449
450    *this << END_BRACKET << std::endl;
451}
452
453void OutputStream::writeObjectFields( const osg::Object* obj )
454{
455    std::string name = obj->libraryName();
456    name += std::string("::") + obj->className();
457
458    ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( name );
459    if ( !wrapper )
460    {
461        OSG_WARN << "OutputStream::writeObject(): Unsupported wrapper class "
462                                << name << std::endl;
463        return;
464    }
465    _fields.push_back( name );
466
467    const StringList& associates = wrapper->getAssociates();
468    for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
469    {
470        const std::string& assocName = *itr;
471        ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
472        if ( !assocWrapper )
473        {
474            OSG_WARN << "OutputStream::writeObject(): Unsupported associated class "
475                                    << assocName << std::endl;
476            continue;
477        }
478        else if ( _useSchemaData )
479        {
480            if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() )
481            {
482                StringList properties;
483                std::vector<int> types;
484                assocWrapper->writeSchema( properties, types );
485               
486                unsigned int size = osg::minimum( properties.size(), types.size() );
487                if ( size>0 )
488                {
489                    std::stringstream propertiesStream;
490                    for ( unsigned int i=0; i<size; ++i )
491                    {
492                        propertiesStream << properties[i] << ":" << types[i] << " ";
493                    }
494                    _inbuiltSchemaMap[assocName] = propertiesStream.str();
495                }
496            }
497        }
498        _fields.push_back( assocWrapper->getName() );
499
500        assocWrapper->write( *this, *obj );
501        if ( getException() ) return;
502
503        _fields.pop_back();
504    }
505    _fields.pop_back();
506
507}
508
509void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType type )
510{
511    _fields.clear();
512    _fields.push_back( "Start" );
513   
514    _out = outIterator;
515    if ( !_out )
516        throwException( "OutputStream: Null stream specified." );
517    if ( getException() ) return;
518   
519    if ( isBinary() )
520    {
521        *this << (unsigned int)type << (unsigned int)OPENSCENEGRAPH_SOVERSION;
522       
523        bool useCompressSource = false;
524        unsigned int attributes = 0;
525
526        if ( _useSchemaData )
527        {
528            attributes |= 0x2;  // Record if we use inbuilt schema data or not
529            useCompressSource = true;
530        }
531        *this << attributes;
532       
533        if ( !_compressorName.empty() )
534        {
535            BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName);
536            if ( !compressor )
537            {
538                OSG_WARN << "OutputStream::start(): No such compressor "
539                                       << _compressorName << std::endl;
540                _compressorName.clear();
541            }
542            else
543            {
544                useCompressSource = true;
545            }
546        }
547        if ( !_compressorName.empty() ) *this << _compressorName;
548        else *this << std::string("0");  // No compressor
549       
550        // Compressors and inbuilt schema use a new stream, which will be merged with the original one at the end.
551        if ( useCompressSource )
552        {
553            _out->flush();
554            _out->setStream( &_compressSource );
555        }
556    }
557    else
558    {
559        std::string typeString("Unknown");
560        switch ( type )
561        {
562        case WRITE_SCENE: typeString = "Scene"; break;
563        case WRITE_IMAGE: typeString = "Image"; break;
564        case WRITE_OBJECT: typeString = "Object"; break;
565        default: break;
566        }
567       
568        *this << typeString << std::endl;
569        *this << PROPERTY("#Version") << (unsigned int)OPENSCENEGRAPH_SOVERSION << std::endl;
570        *this << PROPERTY("#Generator") << std::string("OpenSceneGraph")
571              << std::string(osgGetVersion()) << std::endl;
572        *this << std::endl;
573    }
574    _fields.pop_back();
575}
576
577void OutputStream::compress( std::ostream* ostream )
578{
579    _fields.clear();
580    if ( !isBinary() ) return;
581   
582    std::stringstream schemaSource;
583    if ( _useSchemaData )
584    {
585        _fields.push_back( "SchemaData" );
586       
587        std::string schemaData;
588        for ( std::map<std::string, std::string>::iterator itr=_inbuiltSchemaMap.begin();
589              itr!=_inbuiltSchemaMap.end(); ++itr )
590        {
591            schemaData += itr->first + '=';
592            schemaData += itr->second;
593            schemaData += '\n';
594        }
595       
596        int size = schemaData.size();
597        schemaSource.write( (char*)&size, INT_SIZE );
598        schemaSource.write( schemaData.c_str(), size );
599       
600        _inbuiltSchemaMap.clear();
601        _fields.pop_back();
602    }
603   
604    if ( !_compressorName.empty() )
605    {
606        _fields.push_back( "Compression" );
607        BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName);
608        if ( !compressor || !ostream )
609        {
610            _fields.pop_back();
611            return;
612        }
613       
614        if ( !compressor->compress(*ostream, schemaSource.str() + _compressSource.str()) )
615            throwException( "OutputStream: Failed to compress stream." );
616        if ( getException() ) return;
617        _fields.pop_back();
618    }
619    else if ( _useSchemaData )
620    {
621        std::string str = schemaSource.str() + _compressSource.str();
622        ostream->write( str.c_str(), str.size() );
623    }
624}
625
626void OutputStream::writeSchema( std::ostream& fout )
627{
628    // Write to external ascii stream
629    const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap();
630    for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin();
631          itr!=wrappers.end(); ++itr )
632    {
633        ObjectWrapper* wrapper = itr->second.get();
634        fout << itr->first << " =";
635       
636        StringList properties;
637        std::vector<int> types;
638        wrapper->writeSchema( properties, types );
639       
640        std::string propertiesString;
641        unsigned int size = osg::minimum( properties.size(), types.size() );
642        for ( unsigned int i=0; i<size; ++i )
643        {
644            fout << " " << properties[i] << ":" << types[i];
645        }
646        fout << std::endl;
647    }
648}
649
650// PROTECTED METHODS
651
652template<typename T>
653void OutputStream::writeArrayImplementation( const T* a, int write_size, unsigned int numInRow )
654{
655    *this << write_size << BEGIN_BRACKET;
656    if ( numInRow>1 )
657    {
658        for ( int i=0; i<write_size; ++i )
659        {
660            if ( !(i%numInRow) )
661            {
662                *this << std::endl << (*a)[i];
663            }
664            else
665                *this << (*a)[i];
666        }
667        *this << std::endl;
668    }
669    else
670    {
671        *this << std::endl;
672        for ( int i=0; i<write_size; ++i )
673            *this << (*a)[i] << std::endl;
674    }
675    *this << END_BRACKET << std::endl;
676}
677
678unsigned int OutputStream::findOrCreateArrayID( const osg::Array* array, bool& newID )
679{
680    ArrayMap::iterator itr = _arrayMap.find( array );
681    if ( itr==_arrayMap.end() )
682    {
683        unsigned int id = _arrayMap.size()+1;
684        _arrayMap[array] = id;
685        newID = true;
686        return id;
687    }
688    newID = false;
689    return itr->second;
690}
691
692unsigned int OutputStream::findOrCreateObjectID( const osg::Object* obj, bool& newID )
693{
694    ObjectMap::iterator itr = _objectMap.find( obj );
695    if ( itr==_objectMap.end() )
696    {
697        unsigned int id = _objectMap.size()+1;
698        _objectMap[obj] = id;
699        newID = true;
700        return id;
701    }
702    newID = false;
703    return itr->second;
704}
Note: See TracBrowser for help on using the browser.