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

Revision 12912, 25.0 kB (checked in by robert, 2 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

  • 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);
373
374                for(osg::Image::DataIterator img_itr(img); img_itr.valid(); ++img_itr)
375                {
376                    writeCharArray( (char*)img_itr.data(), img_itr.size() );
377                }
378
379                // _mipmapData
380                unsigned int numMipmaps = img->getNumMipmapLevels()-1;
381                writeSize(numMipmaps);
382                int s = img->s();
383                int t = img->t();
384                int r = img->r();
385                unsigned int offset = 0;
386                for (unsigned int i=0; i<numMipmaps; ++i)
387                {
388                    unsigned int size = osg::Image::computeImageSizeInBytes(s,t,r,img->getPixelFormat(),img->getDataType(),img->getPacking());
389                    offset += size;
390                   
391                    *this << offset;
392
393                    s >>= 1;
394                    t >>= 1;
395                    r >>= 1;
396                    if (s<1) s=1;
397                    if (t<1) t=1;
398                    if (r<1) r=1;                   
399                }
400            }
401            break;
402        case IMAGE_INLINE_FILE:
403            if ( isBinary() )
404            {
405                std::string fullPath = osgDB::findDataFile( img->getFileName() );
406                std::ifstream infile( fullPath.c_str(), std::ios::in|std::ios::binary );
407                if ( infile )
408                {
409                    infile.seekg( 0, std::ios::end );
410                    unsigned int size = infile.tellg();
411                    writeSize(size);
412
413                    if ( size>0 )
414                    {
415                        char* data = new char[size];
416                        if ( !data )
417                        {
418                            throwException( "OutputStream::writeImage(): Out of memory." );
419                            if ( getException() ) return;
420                        }
421
422                        infile.seekg( 0, std::ios::beg );
423                        infile.read( data, size );
424                        writeCharArray( data, size );
425                        delete[] data;
426                    }
427                    infile.close();
428                }
429                else
430                {
431                    OSG_WARN << "OutputStream::writeImage(): Failed to open image file "
432                                        << img->getFileName() << std::endl;
433                    *this << (unsigned int)0;
434                }
435            }
436            break;
437        case IMAGE_EXTERNAL:
438            break;
439        default:
440            break;
441        }
442
443        writeObjectFields( img );
444    }
445
446    // *this << END_BRACKET << std::endl;
447}
448
449void OutputStream::writeObject( const osg::Object* obj )
450{
451    if ( !obj ) return;
452
453    std::string name = obj->libraryName();
454    name += std::string("::") + obj->className();
455
456    bool newID = false;
457    unsigned int id = findOrCreateObjectID( obj, newID );
458
459    *this << name << BEGIN_BRACKET << std::endl;       // Write object name
460    *this << PROPERTY("UniqueID") << id << std::endl;  // Write object ID
461    if ( getException() ) return;
462
463    if (newID)
464    {
465        writeObjectFields(obj);
466    }
467
468    *this << END_BRACKET << std::endl;
469}
470
471void OutputStream::writeObjectFields( const osg::Object* obj )
472{
473    std::string name = obj->libraryName();
474    name += std::string("::") + obj->className();
475
476    ObjectWrapper* wrapper = Registry::instance()->getObjectWrapperManager()->findWrapper( name );
477    if ( !wrapper )
478    {
479        OSG_WARN << "OutputStream::writeObject(): Unsupported wrapper class "
480                                << name << std::endl;
481        return;
482    }
483    _fields.push_back( name );
484
485    const StringList& associates = wrapper->getAssociates();
486    for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr )
487    {
488        const std::string& assocName = *itr;
489        ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName);
490        if ( !assocWrapper )
491        {
492            OSG_WARN << "OutputStream::writeObject(): Unsupported associated class "
493                                    << assocName << std::endl;
494            continue;
495        }
496        else if ( _useSchemaData )
497        {
498            if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() )
499            {
500                StringList properties;
501                std::vector<int> types;
502                assocWrapper->writeSchema( properties, types );
503               
504                unsigned int size = osg::minimum( properties.size(), types.size() );
505                if ( size>0 )
506                {
507                    std::stringstream propertiesStream;
508                    for ( unsigned int i=0; i<size; ++i )
509                    {
510                        propertiesStream << properties[i] << ":" << types[i] << " ";
511                    }
512                    _inbuiltSchemaMap[assocName] = propertiesStream.str();
513                }
514            }
515        }
516        _fields.push_back( assocWrapper->getName() );
517
518        assocWrapper->write( *this, *obj );
519        if ( getException() ) return;
520
521        _fields.pop_back();
522    }
523    _fields.pop_back();
524
525}
526
527void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType type )
528{
529    _fields.clear();
530    _fields.push_back( "Start" );
531   
532    _out = outIterator;
533    if ( !_out )
534        throwException( "OutputStream: Null stream specified." );
535    if ( getException() ) return;
536   
537    if ( isBinary() )
538    {
539        *this << (unsigned int)type << (unsigned int)OPENSCENEGRAPH_SOVERSION;
540       
541        bool useCompressSource = false;
542        unsigned int attributes = 0;
543
544        if ( _useSchemaData )
545        {
546            attributes |= 0x2;  // Record if we use inbuilt schema data or not
547            useCompressSource = true;
548        }
549        *this << attributes;
550       
551        if ( !_compressorName.empty() )
552        {
553            BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName);
554            if ( !compressor )
555            {
556                OSG_WARN << "OutputStream::start(): No such compressor "
557                                       << _compressorName << std::endl;
558                _compressorName.clear();
559            }
560            else
561            {
562                useCompressSource = true;
563            }
564        }
565        if ( !_compressorName.empty() ) *this << _compressorName;
566        else *this << std::string("0");  // No compressor
567       
568        // Compressors and inbuilt schema use a new stream, which will be merged with the original one at the end.
569        if ( useCompressSource )
570        {
571            _out->flush();
572            _out->setStream( &_compressSource );
573        }
574    }
575    else
576    {
577        std::string typeString("Unknown");
578        switch ( type )
579        {
580        case WRITE_SCENE: typeString = "Scene"; break;
581        case WRITE_IMAGE: typeString = "Image"; break;
582        case WRITE_OBJECT: typeString = "Object"; break;
583        default: break;
584        }
585       
586        *this << typeString << std::endl;
587        *this << PROPERTY("#Version") << (unsigned int)OPENSCENEGRAPH_SOVERSION << std::endl;
588        *this << PROPERTY("#Generator") << std::string("OpenSceneGraph")
589              << std::string(osgGetVersion()) << std::endl;
590        *this << std::endl;
591    }
592    _fields.pop_back();
593}
594
595void OutputStream::compress( std::ostream* ostream )
596{
597    _fields.clear();
598    if ( !isBinary() ) return;
599   
600    std::stringstream schemaSource;
601    if ( _useSchemaData )
602    {
603        _fields.push_back( "SchemaData" );
604       
605        std::string schemaData;
606        for ( std::map<std::string, std::string>::iterator itr=_inbuiltSchemaMap.begin();
607              itr!=_inbuiltSchemaMap.end(); ++itr )
608        {
609            schemaData += itr->first + '=';
610            schemaData += itr->second;
611            schemaData += '\n';
612        }
613       
614        int size = schemaData.size();
615        schemaSource.write( (char*)&size, INT_SIZE );
616        schemaSource.write( schemaData.c_str(), size );
617       
618        _inbuiltSchemaMap.clear();
619        _fields.pop_back();
620    }
621   
622    if ( !_compressorName.empty() )
623    {
624        _fields.push_back( "Compression" );
625        BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName);
626        if ( !compressor || !ostream )
627        {
628            _fields.pop_back();
629            return;
630        }
631       
632        if ( !compressor->compress(*ostream, schemaSource.str() + _compressSource.str()) )
633            throwException( "OutputStream: Failed to compress stream." );
634        if ( getException() ) return;
635        _fields.pop_back();
636    }
637    else if ( _useSchemaData )
638    {
639        std::string str = schemaSource.str() + _compressSource.str();
640        ostream->write( str.c_str(), str.size() );
641    }
642}
643
644void OutputStream::writeSchema( std::ostream& fout )
645{
646    // Write to external ascii stream
647    const ObjectWrapperManager::WrapperMap& wrappers = Registry::instance()->getObjectWrapperManager()->getWrapperMap();
648    for ( ObjectWrapperManager::WrapperMap::const_iterator itr=wrappers.begin();
649          itr!=wrappers.end(); ++itr )
650    {
651        ObjectWrapper* wrapper = itr->second.get();
652        fout << itr->first << " =";
653       
654        StringList properties;
655        std::vector<int> types;
656        wrapper->writeSchema( properties, types );
657       
658        std::string propertiesString;
659        unsigned int size = osg::minimum( properties.size(), types.size() );
660        for ( unsigned int i=0; i<size; ++i )
661        {
662            fout << " " << properties[i] << ":" << types[i];
663        }
664        fout << std::endl;
665    }
666}
667
668// PROTECTED METHODS
669
670template<typename T>
671void OutputStream::writeArrayImplementation( const T* a, int write_size, unsigned int numInRow )
672{
673    *this << write_size << BEGIN_BRACKET;
674    if ( numInRow>1 )
675    {
676        for ( int i=0; i<write_size; ++i )
677        {
678            if ( !(i%numInRow) )
679            {
680                *this << std::endl << (*a)[i];
681            }
682            else
683                *this << (*a)[i];
684        }
685        *this << std::endl;
686    }
687    else
688    {
689        *this << std::endl;
690        for ( int i=0; i<write_size; ++i )
691            *this << (*a)[i] << std::endl;
692    }
693    *this << END_BRACKET << std::endl;
694}
695
696unsigned int OutputStream::findOrCreateArrayID( const osg::Array* array, bool& newID )
697{
698    ArrayMap::iterator itr = _arrayMap.find( array );
699    if ( itr==_arrayMap.end() )
700    {
701        unsigned int id = _arrayMap.size()+1;
702        _arrayMap[array] = id;
703        newID = true;
704        return id;
705    }
706    newID = false;
707    return itr->second;
708}
709
710unsigned int OutputStream::findOrCreateObjectID( const osg::Object* obj, bool& newID )
711{
712    ObjectMap::iterator itr = _objectMap.find( obj );
713    if ( itr==_objectMap.end() )
714    {
715        unsigned int id = _objectMap.size()+1;
716        _objectMap[obj] = id;
717        newID = true;
718        return id;
719    }
720    newID = false;
721    return itr->second;
722}
Note: See TracBrowser for help on using the browser.