root/OpenSceneGraph/trunk/src/osgPlugins/osg/ReaderWriterOSG2.cpp @ 13041

Revision 13041, 14.6 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • 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 <osgDB/FileNameUtils>
16#include <osgDB/FileUtils>
17#include <osgDB/Registry>
18#include <osgDB/ObjectWrapper>
19#include <stdlib.h>
20#include "AsciiStreamOperator.h"
21#include "BinaryStreamOperator.h"
22#include "XmlStreamOperator.h"
23
24using namespace osgDB;
25
26#define CATCH_EXCEPTION(s) \
27    if (s.getException()) return (s.getException()->getError() + " At " + s.getException()->getField());
28
29#define OSG_REVERSE(value) ( ((value & 0x000000ff)<<24) | ((value & 0x0000ff00)<<8) | ((value & 0x00ff0000)>>8) | ((value & 0xff000000)>>24) )
30
31InputIterator* readInputIterator( std::istream& fin, const Options* options )
32{
33    bool extensionIsAscii = false, extensionIsXML = false;
34    if ( options )
35    {
36        const std::string& optionString = options->getOptionString();
37        if ( optionString.find("Ascii")!=std::string::npos ) extensionIsAscii = true;
38        else if ( optionString.find("XML")!=std::string::npos ) extensionIsXML = true;
39    }
40
41    if ( !extensionIsAscii && !extensionIsXML )
42    {
43        unsigned int headerLow = 0, headerHigh = 0;
44        fin.read( (char*)&headerLow, INT_SIZE );
45        fin.read( (char*)&headerHigh, INT_SIZE );
46        if ( headerLow==OSG_HEADER_LOW && headerHigh==OSG_HEADER_HIGH )
47        {
48            OSG_INFO<<"Reading OpenSceneGraph binary file with the same endian as this computer."<<std::endl;
49            return new BinaryInputIterator(&fin, 0); // endian the same so no byte swap required
50        }
51        else if ( headerLow==OSG_REVERSE(OSG_HEADER_LOW) && headerHigh==OSG_REVERSE(OSG_HEADER_HIGH) )
52        {
53            OSG_INFO<<"Reading OpenSceneGraph binary file with the different endian to this computer, doing byte swap."<<std::endl;
54            return new BinaryInputIterator(&fin, 1); // endian different so byte swap required
55        }
56
57        fin.seekg( 0, std::ios::beg );
58    }
59
60    if ( !extensionIsXML )
61    {
62        std::string header; fin >> header;
63        if ( header=="#Ascii" )
64        {
65            return new AsciiInputIterator(&fin);
66        }
67        fin.seekg( 0, std::ios::beg );
68    }
69
70    if ( 1 )
71    {
72        std::string header; std::getline( fin, header );
73        if ( !header.compare(0, 5, "<?xml") )
74        {
75            return new XmlInputIterator(&fin);
76        }
77        fin.seekg( 0, std::ios::beg );
78    }
79    return NULL;
80}
81
82OutputIterator* writeOutputIterator( std::ostream& fout, const Options* options )
83{
84    // Read precision parameter, for text & XML formats
85    int precision(-1);
86    if ( options ) {
87        std::istringstream iss(options->getOptionString());
88        std::string opt;
89        while (iss >> opt)
90        {
91            if(opt=="PRECISION" || opt=="precision")
92            {
93                iss >> precision;
94            }
95        }
96    }
97
98    if ( options && options->getOptionString().find("Ascii")!=std::string::npos )
99    {
100        fout << std::string("#Ascii") << ' ';
101        return new AsciiOutputIterator(&fout, precision);
102    }
103    else if ( options && options->getOptionString().find("XML")!=std::string::npos )
104    {
105        fout << std::string("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>") << std::endl;
106        return new XmlOutputIterator(&fout, precision);
107    }
108    else
109    {
110        unsigned int low = OSG_HEADER_LOW, high = OSG_HEADER_HIGH;
111        fout.write( (char*)&low, INT_SIZE );
112        fout.write( (char*)&high, INT_SIZE );
113        return new BinaryOutputIterator(&fout);
114    }
115}
116
117class ReaderWriterOSG2 : public osgDB::ReaderWriter
118{
119public:
120    ReaderWriterOSG2()
121    {
122        supportsExtension( "osg2", "OpenSceneGraph extendable format" );
123        supportsExtension( "osgt", "OpenSceneGraph extendable ascii format" );
124        supportsExtension( "osgb", "OpenSceneGraph extendable binary format" );
125        supportsExtension( "osgx", "OpenSceneGraph extendable XML format" );
126
127        supportsOption( "Ascii", "Import/Export option: Force reading/writing ascii file" );
128        supportsOption( "XML", "Import/Export option: Force reading/writing XML file" );
129        supportsOption( "ForceReadingImage", "Import option: Load an empty image instead if required file missed" );
130        supportsOption( "SchemaData", "Export option: Record inbuilt schema data into a binary file" );
131        supportsOption( "SchemaFile=<file>", "Import/Export option: Use/Record an ascii schema file" );
132        supportsOption( "Compressor=<name>", "Export option: Use an inbuilt or user-defined compressor" );
133        supportsOption( "WriteImageHint=<hint>", "Export option: Hint of writing image to stream: "
134                        "<IncludeData> writes Image::data() directly; "
135                        "<IncludeFile> writes the image file itself to stream; "
136                        "<UseExternal> writes only the filename; "
137                        "<WriteOut> writes Image::data() to disk as external file." );
138    }
139
140    virtual const char* className() const { return "OpenSceneGraph Native Format Reader/Writer"; }
141
142
143    Options* prepareReading( ReadResult& result, std::string& fileName, std::ios::openmode& mode, const Options* options ) const
144    {
145        std::string ext = osgDB::getLowerCaseFileExtension( fileName );
146        if ( !acceptsExtension(ext) )
147        {
148            result = ReadResult::FILE_NOT_HANDLED;
149            return 0;
150        }
151        fileName = osgDB::findDataFile( fileName, options );
152        if ( fileName.empty() )
153        {
154            result = ReadResult::FILE_NOT_FOUND;
155            return 0;
156        }
157
158        osg::ref_ptr<Options> local_opt = options ?
159            static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
160        local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
161        if ( ext=="osgt" ) local_opt->setOptionString( local_opt->getOptionString() + " Ascii" );
162        else if ( ext=="osgx" ) local_opt->setOptionString( local_opt->getOptionString() + " XML" );
163        else mode |= std::ios::binary;
164
165        return local_opt.release();
166    }
167
168    virtual ReadResult readObject( const std::string& file, const Options* options ) const
169    {
170        ReadResult result = ReadResult::FILE_LOADED;
171        std::string fileName = file;
172        std::ios::openmode mode = std::ios::in;
173        Options* local_opt = prepareReading( result, fileName, mode, options );
174        if ( !result.success() ) return result;
175
176        osgDB::ifstream istream( fileName.c_str(), mode );
177        return readObject( istream, local_opt );
178    }
179
180    virtual ReadResult readObject( std::istream& fin, const Options* options ) const
181    {
182        osg::ref_ptr<InputIterator> ii = readInputIterator(fin, options);
183        if ( !ii ) return ReadResult::FILE_NOT_HANDLED;
184
185        InputStream is( options );
186
187        osgDB::InputStream::ReadType readType = is.start(ii.get());
188        if ( readType==InputStream::READ_UNKNOWN )
189        {
190            CATCH_EXCEPTION(is);
191            return ReadResult::FILE_NOT_HANDLED;
192        }
193        is.decompress(); CATCH_EXCEPTION(is);
194
195        osg::Object* obj = is.readObject(); CATCH_EXCEPTION(is);
196        return obj;
197    }
198
199    virtual ReadResult readImage( const std::string& file, const Options* options ) const
200    {
201        ReadResult result = ReadResult::FILE_LOADED;
202        std::string fileName = file;
203        std::ios::openmode mode = std::ios::in;
204        Options* local_opt = prepareReading( result, fileName, mode, options );
205        if ( !result.success() ) return result;
206
207        osgDB::ifstream istream( fileName.c_str(), mode );
208        return readImage( istream, local_opt );
209    }
210
211    virtual ReadResult readImage( std::istream& fin, const Options* options ) const
212    {
213        osg::ref_ptr<InputIterator> ii = readInputIterator(fin, options);
214        if ( !ii ) return ReadResult::FILE_NOT_HANDLED;
215
216        InputStream is( options );
217        if ( is.start(ii.get())!=InputStream::READ_IMAGE )
218        {
219            CATCH_EXCEPTION(is);
220            return ReadResult::FILE_NOT_HANDLED;
221        }
222        is.decompress(); CATCH_EXCEPTION(is);
223        osg::Image* image = is.readImage(); CATCH_EXCEPTION(is);
224        return image;
225    }
226
227    virtual ReadResult readNode( const std::string& file, const Options* options ) const
228    {
229        ReadResult result = ReadResult::FILE_LOADED;
230        std::string fileName = file;
231        std::ios::openmode mode = std::ios::in;
232        Options* local_opt = prepareReading( result, fileName, mode, options );
233        if ( !result.success() ) return result;
234
235        osgDB::ifstream istream( fileName.c_str(), mode );
236        return readNode( istream, local_opt );
237    }
238
239    virtual ReadResult readNode( std::istream& fin, const Options* options ) const
240    {
241        osg::ref_ptr<InputIterator> ii = readInputIterator(fin, options);
242        if ( !ii ) return ReadResult::FILE_NOT_HANDLED;
243
244        InputStream is( options );
245        if ( is.start(ii.get())!=InputStream::READ_SCENE )
246        {
247            CATCH_EXCEPTION(is);
248            return ReadResult::FILE_NOT_HANDLED;
249        }
250
251        is.decompress(); CATCH_EXCEPTION(is);
252        osg::Node* node = dynamic_cast<osg::Node*>(is.readObject()); CATCH_EXCEPTION(is);
253        return node;
254    }
255
256    Options* prepareWriting( WriteResult& result, const std::string& fileName, std::ios::openmode& mode, const Options* options ) const
257    {
258        std::string ext = osgDB::getFileExtension( fileName );
259        if ( !acceptsExtension(ext) ) result = WriteResult::FILE_NOT_HANDLED;
260
261        osg::ref_ptr<Options> local_opt = options ?
262            static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
263        local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
264        if ( ext=="osgt" ) local_opt->setOptionString( local_opt->getOptionString() + " Ascii" );
265        else if ( ext=="osgx" ) local_opt->setOptionString( local_opt->getOptionString() + " XML" );
266        else mode |= std::ios::binary;
267
268        return local_opt.release();
269    }
270
271    virtual WriteResult writeObject( const osg::Object& object, const std::string& fileName, const Options* options ) const
272    {
273        WriteResult result = WriteResult::FILE_SAVED;
274        std::ios::openmode mode = std::ios::out;
275        osg::ref_ptr<Options> local_opt = prepareWriting( result, fileName, mode, options );
276        if ( !result.success() ) return result;
277
278        osgDB::ofstream fout( fileName.c_str(), mode );
279        if ( !fout ) return WriteResult::ERROR_IN_WRITING_FILE;
280
281        result = writeObject( object, fout, local_opt.get() );
282        fout.close();
283        return result;
284    }
285
286    virtual WriteResult writeObject( const osg::Object& object, std::ostream& fout, const Options* options ) const
287    {
288        osg::ref_ptr<OutputIterator> oi = writeOutputIterator(fout, options);
289
290        OutputStream os( options );
291        os.start( oi.get(), OutputStream::WRITE_OBJECT ); CATCH_EXCEPTION(os);
292        os.writeObject( &object ); CATCH_EXCEPTION(os);
293        os.compress( &fout ); CATCH_EXCEPTION(os);
294
295        oi->flush();
296        if ( !os.getSchemaName().empty() )
297        {
298            osgDB::ofstream schemaStream( os.getSchemaName().c_str(), std::ios::out );
299            if ( !schemaStream.fail() ) os.writeSchema( schemaStream );
300            schemaStream.close();
301        }
302
303        if ( fout.fail() ) return WriteResult::ERROR_IN_WRITING_FILE;
304        return WriteResult::FILE_SAVED;
305    }
306
307    virtual WriteResult writeImage( const osg::Image& image, const std::string& fileName, const Options* options ) const
308    {
309        WriteResult result = WriteResult::FILE_SAVED;
310        std::ios::openmode mode = std::ios::out;
311        osg::ref_ptr<Options> local_opt = prepareWriting( result, fileName, mode, options );
312        if ( !result.success() ) return result;
313
314        osgDB::ofstream fout( fileName.c_str(), mode );
315        if ( !fout ) return WriteResult::ERROR_IN_WRITING_FILE;
316
317        result = writeImage( image, fout, local_opt.get() );
318        fout.close();
319        return result;
320    }
321
322    virtual WriteResult writeImage( const osg::Image& image, std::ostream& fout, const Options* options ) const
323    {
324        osg::ref_ptr<OutputIterator> oi = writeOutputIterator(fout, options);
325
326        OutputStream os( options );
327        os.start( oi.get(), OutputStream::WRITE_IMAGE ); CATCH_EXCEPTION(os);
328        os.writeImage( &image ); CATCH_EXCEPTION(os);
329        os.compress( &fout ); CATCH_EXCEPTION(os);
330
331        oi->flush();
332        if ( !os.getSchemaName().empty() )
333        {
334            osgDB::ofstream schemaStream( os.getSchemaName().c_str(), std::ios::out );
335            if ( !schemaStream.fail() ) os.writeSchema( schemaStream );
336            schemaStream.close();
337        }
338
339        if ( fout.fail() ) return WriteResult::ERROR_IN_WRITING_FILE;
340        return WriteResult::FILE_SAVED;
341    }
342
343    virtual WriteResult writeNode( const osg::Node& node, const std::string& fileName, const Options* options ) const
344    {
345        WriteResult result = WriteResult::FILE_SAVED;
346        std::ios::openmode mode = std::ios::out;
347        osg::ref_ptr<Options> local_opt = prepareWriting( result, fileName, mode, options );
348        if ( !result.success() ) return result;
349
350        osgDB::ofstream fout( fileName.c_str(), mode );
351        if ( !fout ) return WriteResult::ERROR_IN_WRITING_FILE;
352
353        result = writeNode( node, fout, local_opt.get() );
354        fout.close();
355        return result;
356    }
357
358    virtual WriteResult writeNode( const osg::Node& node, std::ostream& fout, const Options* options ) const
359    {
360        osg::ref_ptr<OutputIterator> oi = writeOutputIterator(fout, options);
361
362        OutputStream os( options );
363        os.start( oi.get(), OutputStream::WRITE_SCENE ); CATCH_EXCEPTION(os);
364        os.writeObject( &node ); CATCH_EXCEPTION(os);
365        os.compress( &fout ); CATCH_EXCEPTION(os);
366
367        oi->flush();
368        if ( !os.getSchemaName().empty() )
369        {
370            osgDB::ofstream schemaStream( os.getSchemaName().c_str(), std::ios::out );
371            if ( !schemaStream.fail() ) os.writeSchema( schemaStream );
372            schemaStream.close();
373        }
374
375        if ( fout.fail() ) return WriteResult::ERROR_IN_WRITING_FILE;
376        return WriteResult::FILE_SAVED;
377    }
378};
379
380REGISTER_OSGPLUGIN( osg2, ReaderWriterOSG2 )
Note: See TracBrowser for help on using the browser.