root/OpenSceneGraph/trunk/include/osgDB/Registry @ 3272

Revision 3272, 22.1 kB (checked in by robert, 10 years ago)

Added docs for CacheObjectHints?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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
14#ifndef OSGDB_REGISTRY
15#define OSGDB_REGISTRY 1
16
17#include <osg/ref_ptr>
18#include <osg/ArgumentParser>
19
20#include <osgDB/DynamicLibrary>
21#include <osgDB/ReaderWriter>
22#include <osgDB/DotOsgWrapper>
23#include <osgDB/DatabasePager>
24
25#include <vector>
26#include <map>
27#include <string>
28#include <deque>
29
30
31namespace osgDB {
32
33/** basic structure for custom runtime inheritance checking */
34struct basic_type_wrapper {
35    virtual bool matches(const osg::Object *proto) const = 0;
36};
37
38/** a class template that checks inheritance between a given
39    Object's class and a class defined at compile time through
40        the template parameter T.
41        This is used in conjunction with readObjectOfType() to
42        specify an abstract class as reference type.
43**/
44template<class T>
45struct type_wrapper: basic_type_wrapper {
46    bool matches(const osg::Object *proto) const
47    {
48        return dynamic_cast<const T*>(proto) != 0;
49    }
50};
51
52/** list of directories to search through which searching for files. */
53typedef std::deque<std::string> FilePathList;
54
55/**
56    Registry is a singleton factory which stores
57    the reader/writers which are linked in
58    at runtime for reading non-native file formats.
59
60    The RegisterDotOsgWrapperProxy can be used to automatically register
61    DotOsgWrappers, at runtime with the Registry. A DotOsgWrapper encapsulates
62    the functions that can read and write to the .osg for each osg::Object.
63
64    The RegisterReaderWriterProxy can be used to automatically
65    register at runtime a reader/writer with the Registry.
66*/
67class OSGDB_EXPORT Registry : public osg::Referenced
68{
69    public:
70
71        /// bit mask for setting up which object types get cached by readObject/Image/HeightField/Node(filename) calls
72        enum CacheHintOptions
73        {   /// do not cache objects of any type
74            CACHE_NONE          = 0,
75           
76            /// cache nodes loaded via readNode(filename)
77            CACHE_NODES         = 1,
78           
79            /// cache images loaded via readImage(filename)
80            CACHE_IMAGES        = 2,
81             
82            /// cache heightfield loaded via readHeightField(filename)
83            CACHE_HEIGHTFIELDS  = 4,
84           
85            /// cache objects loaded via readObject(filename)
86            CACHE_OBJECTS       = 8,
87           
88            /// cache on all read*(filename) calls
89            CACHE_ALL           = CACHE_NODES |
90                                  CACHE_IMAGES |
91                                  CACHE_HEIGHTFIELDS |
92                                  CACHE_OBJECTS
93        };
94
95
96       
97        static Registry* instance(bool erase = false);
98
99        /** read the command line arguments.*/
100        void readCommandLine(osg::ArgumentParser& commandLine);
101
102        /** register an .fileextension alias to mapExt toExt, the later
103          * should the the extension name of the readerwriter plugin library.
104          * For example to map .tif files to the tiff loader, use
105          * addExtAlias("tif","tiff") which will enable .tif to be read
106          * by the libdb_tiff readerwriter plugin.*/
107        void addFileExtensionAlias(const std::string mapExt, const std::string toExt);
108
109        void addDotOsgWrapper(DotOsgWrapper* wrapper);
110        void removeDotOsgWrapper(DotOsgWrapper* wrapper);
111
112        void addReaderWriter(ReaderWriter* rw);
113        void removeReaderWriter(ReaderWriter* rw);
114
115        /** create the platform specific library name associated with file.*/
116        std::string createLibraryNameForFile(const std::string& fileName);
117
118        /** create the platform specific library name associated with file extension.*/
119        std::string createLibraryNameForExtension(const std::string& ext);
120
121        /** create the platform specific library name associated with nodekit library name.*/
122        std::string createLibraryNameForNodeKit(const std::string& name);
123
124        /** find the library in the SG_LIBRARY_PATH and load it.*/
125        bool loadLibrary(const std::string& fileName);
126        /** close the attached library with specified name.*/
127        bool closeLibrary(const std::string& fileName);
128        /** close all libraries.*/
129        void closeAllLibraries();
130
131        /** get a reader writer which handles specified extension.*/
132        ReaderWriter* getReaderWriterForExtension(const std::string& ext);
133 
134        osg::Object*         readObjectOfType(const osg::Object& compObj,Input& fr);       
135        osg::Object*         readObjectOfType(const basic_type_wrapper &btw, Input& fr);
136
137        osg::Object*         readObject(Input& fr);
138        osg::Image*          readImage(Input& fr);
139        osg::Drawable*       readDrawable(Input& fr);
140        osg::StateAttribute* readStateAttribute(Input& fr);
141        osg::Node*           readNode(Input& fr);
142       
143        bool                 writeObject(const osg::Object& obj,Output& fw);
144
145       
146        class ReadFileCallback : public osg::Referenced
147        {
148        public:
149       
150            virtual ReaderWriter::ReadResult readObject(const std::string& filename, CacheHintOptions options)
151            {
152                return osgDB::Registry::instance()->readObjectImplementation(filename,options);
153            }
154
155            virtual ReaderWriter::ReadResult readImage(const std::string& filename, CacheHintOptions options)
156            {
157                return osgDB::Registry::instance()->readImageImplementation(filename,options);
158            }
159           
160            virtual ReaderWriter::ReadResult readHeightField(const std::string& filename, CacheHintOptions options)
161            {
162                return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
163            }
164           
165            virtual ReaderWriter::ReadResult readNode(const std::string& filename, CacheHintOptions options)
166            {
167                return osgDB::Registry::instance()->readNodeImplementation(filename,options);
168            }
169           
170        protected:
171               virtual ~ReadFileCallback() {}
172        };
173
174        /** Set the Registry callback to use in place of the default readFile calls.*/
175        void setReadFileCallback( ReadFileCallback* cb) { _readFileCallback = cb; }
176
177        /** Get the readFile callback.*/
178        ReadFileCallback* getReadFileCallback() { return _readFileCallback.get(); }
179       
180        /** Get the const readFile callback.*/
181        const ReadFileCallback* getReadFileCallback() const { return _readFileCallback.get(); }
182
183
184        ReaderWriter::ReadResult readObject(const std::string& fileName,CacheHintOptions useObjectCache)
185        {
186            if (_readFileCallback.valid()) return _readFileCallback->readObject(fileName,useObjectCache);
187            else return readObjectImplementation(fileName,useObjectCache);
188        }
189        ReaderWriter::ReadResult readObjectImplementation(const std::string& fileName,CacheHintOptions useObjectCache);
190       
191        ReaderWriter::ReadResult readImage(const std::string& fileName,CacheHintOptions useObjectCache)
192        {
193            if (_readFileCallback.valid()) return _readFileCallback->readImage(fileName,useObjectCache);
194            else return readImageImplementation(fileName,useObjectCache);
195        }
196        ReaderWriter::ReadResult readImageImplementation(const std::string& fileName,CacheHintOptions useObjectCache);
197
198        ReaderWriter::ReadResult readHeightField(const std::string& fileName,CacheHintOptions useObjectCache)
199        {
200            if (_readFileCallback.valid()) return _readFileCallback->readHeightField(fileName,useObjectCache);
201            else return readHeightFieldImplementation(fileName,useObjectCache);
202        }
203        ReaderWriter::ReadResult readHeightFieldImplementation(const std::string& fileName,CacheHintOptions useObjectCache);
204
205        ReaderWriter::ReadResult readNode(const std::string& fileName,CacheHintOptions useObjectCache)
206        {
207            if (_readFileCallback.valid()) return _readFileCallback->readNode(fileName,useObjectCache);
208            else return readNodeImplementation(fileName,useObjectCache);
209        }
210        ReaderWriter::ReadResult readNodeImplementation(const std::string& fileName,CacheHintOptions useObjectCache);
211
212
213        class WriteFileCallback : public osg::Referenced
214        {
215        public:
216       
217            virtual ReaderWriter::WriteResult writeObject(const osg::Object& obj, const std::string& fileName)
218            {
219                return osgDB::Registry::instance()->writeObjectImplementation(obj,fileName);
220            }
221
222            virtual ReaderWriter::WriteResult writeImage(const osg::Image& obj, const std::string& fileName)
223            {
224                return osgDB::Registry::instance()->writeImageImplementation(obj,fileName);
225            }
226           
227            virtual ReaderWriter::WriteResult writeHeightField(const osg::HeightField& obj, const std::string& fileName)
228            {
229                return osgDB::Registry::instance()->writeHeightFieldImplementation(obj,fileName);
230            }
231           
232            virtual ReaderWriter::WriteResult writeNode(const osg::Node& obj, const std::string& fileName)
233            {
234                return osgDB::Registry::instance()->writeNodeImplementation(obj,fileName);
235            }
236           
237        protected:
238               virtual ~WriteFileCallback() {}
239        };
240
241        /** Set the Registry callback to use in place of the default writeFile calls.*/
242        void setWriteFileCallback( WriteFileCallback* cb) { _writeFileCallback = cb; }
243
244        /** Get the writeFile callback.*/
245        WriteFileCallback* getWriteFileCallback() { return _writeFileCallback.get(); }
246       
247        /** Get the const writeFile callback.*/
248        const WriteFileCallback* getWriteFileCallback() const { return _writeFileCallback.get(); }
249
250
251        ReaderWriter::WriteResult writeObject(const osg::Object& obj, const std::string& fileName)
252        {
253            if (_writeFileCallback.valid()) return _writeFileCallback->writeObject(obj,fileName);
254            else return writeObjectImplementation(obj,fileName);
255        }
256        ReaderWriter::WriteResult writeObjectImplementation(const osg::Object& obj, const std::string& fileName);
257
258        ReaderWriter::WriteResult writeImage(const osg::Image& obj, const std::string& fileName)
259        {
260            if (_writeFileCallback.valid()) return _writeFileCallback->writeImage(obj,fileName);
261            else return writeImageImplementation(obj,fileName);
262        }
263        ReaderWriter::WriteResult writeImageImplementation(const osg::Image& obj, const std::string& fileName);
264
265        ReaderWriter::WriteResult writeHeightField(const osg::HeightField& obj, const std::string& fileName)
266        {
267            if (_writeFileCallback.valid()) return _writeFileCallback->writeHeightField(obj,fileName);
268            else return writeHeightFieldImplementation(obj,fileName);
269        }
270        ReaderWriter::WriteResult writeHeightFieldImplementation(const osg::HeightField& obj, const std::string& fileName);
271
272        ReaderWriter::WriteResult writeNode(const osg::Node& node, const std::string& fileName)
273        {
274            if (_writeFileCallback.valid()) return _writeFileCallback->writeNode(node,fileName);
275            else return writeNodeImplementation(node,fileName);
276        }
277        ReaderWriter::WriteResult writeNodeImplementation(const osg::Node& node, const std::string& fileName);
278       
279       
280        void setCreateNodeFromImage(bool flag) { _createNodeFromImage = flag; }
281        bool getCreateNodeFromImage() const { return _createNodeFromImage; }
282
283
284        void setOptions(ReaderWriter::Options* opt) { _options = opt; }
285        ReaderWriter::Options* getOptions() { return _options.get(); }
286        const ReaderWriter::Options*  getOptions() const { return _options.get(); }
287
288
289        /** initilize both the Data and Library FilePaths, by default called by the
290          * constructor, so it should only be required if you want to force
291          * the re-reading of environmental variables.*/
292        void initFilePathLists() { initDataFilePathList(); initLibraryFilePathList(); }
293       
294        /** initilize the Data FilePath by reading the OSG_FILE_PATH environmental variable.*/
295        void initDataFilePathList();
296
297        /** Set the data file path using a list of paths stored in a FilePath, which is used when search for data files.*/
298        void setDataFilePathList(const FilePathList& filepath) { _dataFilePath = filepath; }
299
300        /** Set the data file path using a single string deliminated either with ';' (Windows) or ':' (All other platforms), which is used when search for data files.*/
301        void setDataFilePathList(const std::string& paths) { _dataFilePath.clear(); convertStringPathIntoFilePathList(paths,_dataFilePath); }
302
303        /** get the data file path which is used when search for data files.*/
304        FilePathList& getDataFilePathList() { return _dataFilePath; }
305
306        /** get the const data file path which is used when search for data files.*/
307        const FilePathList& getDataFilePathList() const { return _dataFilePath; }
308
309        /** initilize the Library FilePath by reading the OSG_LIBRARY_PATH
310          * and the appropriate system environmental variables*/
311        void initLibraryFilePathList();
312
313        /** Set the library file path using a list of paths stored in a FilePath, which is used when search for data files.*/
314        void setLibraryFilePathList(const FilePathList& filepath) { _libraryFilePath = filepath; }
315
316        /** Set the library file path using a single string deliminated either with ';' (Windows) or ':' (All other platforms), which is used when search for data files.*/
317        void setLibraryFilePathList(const std::string& paths) { _libraryFilePath.clear(); convertStringPathIntoFilePathList(paths,_libraryFilePath); }
318
319        /** get the library file path which is used when search for library (dso/dll's) files.*/
320        FilePathList& getLibraryFilePathList() { return _libraryFilePath; }
321       
322        /** get the const library file path which is used when search for library (dso/dll's) files.*/
323        const FilePathList& getLibraryFilePathList() const { return _libraryFilePath; }
324
325        /** convert a string containing a list of paths  deliminated either with ';' (Windows) or ':' (All other platforms) into FilePath represetation.*/
326        static void convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath);
327
328
329        /** For each object in the cache which has an reference count greater than 1
330          * (and therefore referenced by elsewhere in the application) set the time stamp
331          * for that object in the cache to specified time.
332          * This would typically be called once per frame by applications which are doing database paging,
333          * and need to prune objects that are no longer required.
334          * Time value is time in sceonds.*/
335        void updateTimeStampOfObjectsInCacheWithExtenalReferences(double currentTime);
336
337        /** Removed object in the cache which have a time stamp at or before the specified expiry time.
338          * This would typically be called once per frame by applications which are doing database paging,
339          * and need to prune objects that are no longer required, and called after the a called
340          * after the call to updateTimeStampOfObjectsInCacheWithExtenalReferences(currentTime).
341          * Note, the currentTime is not the expiryTime, one would typically set the expiry time
342          * to a fixed amount of time before currentTime, such as expiryTime = currentTime-10.0.
343          * Time value is time in sceonds.*/
344        void removeExpiredObjectsInCache(double expiryTime);
345       
346        /** Remove all objects in the cache regardless of having external references or expiry times.*/
347        void clearObjectCache();
348
349        /** Add a filename,object,timestamp tripple to the Registry::ObjectCache.*/
350        void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0);
351       
352        /** Set whether the Registry::ObjectCache should be used by default.*/
353        void setUseObjectCacheHint(CacheHintOptions useObjectCache) { _useObjectCacheHint = useObjectCache; }
354
355        /** Get whether the Registry::ObjectCache should be used by default.*/
356        CacheHintOptions getUseObjectCacheHint() const { return _useObjectCacheHint; }
357
358        /** get the attached library with specified name.*/
359        DynamicLibrary*              getLibrary(const std::string& fileName);
360
361        typedef std::vector< osg::ref_ptr<ReaderWriter> >               ReaderWriterList;
362       
363       
364        /** Set the DatabasePager.*/
365        void setDatabasePager(DatabasePager* databasePager) { _databasePager = databasePager; }
366
367        /** Get the DatabasePager, creating one if one is not already created.*/
368        DatabasePager* getOrCreateDatabasePager();
369       
370        /** Get the DatabasePager. Return 0 if no DatabasePager has been assigned.*/
371        DatabasePager* getDatabasePager() { return _databasePager.get(); }
372
373       
374        /** Set the SharedStateManager.*/
375        void setSharedStateManager(SharedStateManager* SharedStateManager) { _sharedStateManager = SharedStateManager; }
376
377        /** Get the SharedStateManager, creating one if one is not already created.*/
378        SharedStateManager* getOrCreateSharedStateManager();
379       
380        /** Get the SharedStateManager. Return 0 if no SharedStateManager has been assigned.*/
381        SharedStateManager* getSharedStateManager() { return _sharedStateManager.get(); }
382
383    protected:
384
385        virtual ~Registry();
386
387        typedef std::map< std::string, osg::ref_ptr<DotOsgWrapper> >    DotOsgWrapperMap;
388        typedef std::vector< osg::ref_ptr<DynamicLibrary> >             DynamicLibraryList;
389        typedef std::map< std::string, std::string>                     ExtensionAliasMap;
390       
391        typedef std::pair<osg::ref_ptr<osg::Object>, double >           ObjectTimeStampPair;
392        typedef std::map<std::string, ObjectTimeStampPair >             ObjectCache;
393
394        /** constructor is private, as its a singleton, preventing
395            construction other than via the instance() method and
396            therefore ensuring only one copy is ever constructed*/
397        Registry();
398       
399        /** get the attached library with specified name.*/
400        DynamicLibraryList::iterator getLibraryItr(const std::string& fileName);
401
402        bool _createNodeFromImage;
403
404        osg::Object*       readObject(DotOsgWrapperMap& dowMap,Input& fr);
405
406        void eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper);
407
408        ReaderWriter::ReadResult readObject(const std::string& fileName);
409        ReaderWriter::ReadResult readImage(const std::string& fileName);
410        ReaderWriter::ReadResult readHeightField(const std::string& fileName);
411        ReaderWriter::ReadResult readNode(const std::string& fileName);
412
413        osg::ref_ptr<ReadFileCallback>      _readFileCallback;
414        osg::ref_ptr<WriteFileCallback>     _writeFileCallback;
415
416        DotOsgWrapperMap   _objectWrapperMap;
417        DotOsgWrapperMap   _imageWrapperMap;
418        DotOsgWrapperMap   _drawableWrapperMap;
419        DotOsgWrapperMap   _stateAttrWrapperMap;
420        DotOsgWrapperMap   _nodeWrapperMap;
421       
422        DotOsgWrapperMap   _classNameWrapperMap;
423
424        ReaderWriterList    _rwList;
425        DynamicLibraryList  _dlList;
426
427        bool _openingLibrary;
428   
429        // map to alias to extensions to plugins.
430        ExtensionAliasMap  _extAliasMap;
431       
432        // options to pass to reader writers.
433        osg::ref_ptr<ReaderWriter::Options>  _options;
434       
435        FilePathList       _dataFilePath;
436        FilePathList       _libraryFilePath;
437
438        CacheHintOptions   _useObjectCacheHint;       
439        ObjectCache         _objectCache;
440       
441        osg::ref_ptr<DatabasePager>         _databasePager;
442        osg::ref_ptr<SharedStateManager>    _sharedStateManager;
443
444};
445
446/** read the command line arguments.*/
447inline void readCommandLine(osg::ArgumentParser& parser)
448{
449    Registry::instance()->readCommandLine(parser);
450}
451
452/**  Proxy class for automatic registration of DotOsgWrappers with the Registry.*/
453class RegisterDotOsgWrapperProxy
454{
455    public:
456   
457        RegisterDotOsgWrapperProxy(osg::Object* proto,
458                                   const std::string& name,
459                                   const std::string& associates,
460                                   DotOsgWrapper::ReadFunc readFunc,
461                                   DotOsgWrapper::WriteFunc writeFunc,
462                                   DotOsgWrapper::ReadWriteMode readWriteMode=DotOsgWrapper::READ_AND_WRITE)
463        {
464            if (Registry::instance())
465            {
466                _wrapper = new DotOsgWrapper(proto,name,associates,readFunc,writeFunc,readWriteMode);
467                Registry::instance()->addDotOsgWrapper(_wrapper.get());
468            }
469        }
470       
471        ~RegisterDotOsgWrapperProxy()
472        {
473            if (Registry::instance())
474            {
475                Registry::instance()->removeDotOsgWrapper(_wrapper.get());
476            }
477        }
478       
479    protected:
480        osg::ref_ptr<DotOsgWrapper> _wrapper;
481};
482
483/** Proxy class for automatic registration of reader/writers with the Registry.*/
484template<class T>
485class RegisterReaderWriterProxy
486{
487    public:
488        RegisterReaderWriterProxy()
489        {
490            if (Registry::instance())
491            {
492                _rw = new T;
493                Registry::instance()->addReaderWriter(_rw.get());
494            }
495        }
496
497        ~RegisterReaderWriterProxy()
498        {
499            if (Registry::instance())
500            {
501                Registry::instance()->removeReaderWriter(_rw.get());
502            }
503        }
504       
505        T* get() { return _rw.get(); }
506       
507    protected:
508        osg::ref_ptr<T> _rw;
509};
510
511}
512
513#endif
Note: See TracBrowser for help on using the browser.