]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/ModelRegistry.hxx
Make return type from loadPagedModel explicit.
[simgear.git] / simgear / scene / model / ModelRegistry.hxx
1 // ModelRegistry.hxx -- interface to the OSG model registry
2 //
3 // Copyright (C) 2005-2007 Mathias Froehlich 
4 // Copyright (C) 2007  Tim Moore <timoore@redhat.com>
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 #ifndef _SG_MODELREGISTRY_HXX
20 #define _SG_MODELREGISTRY_HXX 1
21
22 #include <osg/ref_ptr>
23 #include <osg/Node>
24 #include <osgDB/FileUtils>
25 #include <osgDB/FileNameUtils>
26 #include <osgDB/ReaderWriter>
27 #include <osgDB/Registry>
28
29 #include <simgear/compiler.h>
30 #include <simgear/scene/util/OsgSingleton.hxx>
31
32 #include <string>
33 #include <map>
34
35 // Class to register per file extension read callbacks with the OSG
36 // registry, mostly to control caching and post load optimization /
37 // copying that happens above the level of the ReaderWriter.
38 namespace simgear
39 {
40
41 // Different caching and optimization strategies are needed for
42 // different file types. Most loaded files should be optimized and the
43 // optimized version should be cached. When an .osg file is
44 // substituted for another, it is assumed to be optimized already but
45 // it should be cached too (under the name of the original?). .stg
46 // files should not be cached (that's the pager's job) but the files
47 // it causes to be loaded should be. .btg files are already optimized
48 // and shouldn't be cached.
49 //
50 // Complicating this is the effect that removing CACHE_NODES has from
51 // the ReaderWriter options: it switches the object cache with an
52 // empty one, so that's not an option for the files that could be
53 // loaded from a .stg file. So, we'll let
54 // Registry::readNodeImplementation cache a loaded file and then add
55 // the optimized version to the cache ourselves, replacing the
56 // original subgraph.
57 //
58 // To support all these options with a minimum of duplication, the
59 // readNode function is specified as a template with a bunch of
60 // pluggable (and predefined) policies.
61 template <typename ProcessPolicy, typename CachePolicy, typename OptimizePolicy,
62           typename SubstitutePolicy, typename BVHPolicy>
63 class ModelRegistryCallback : public osgDB::Registry::ReadFileCallback {
64 public:
65     ModelRegistryCallback(const std::string& extension) :
66         _processPolicy(extension), _cachePolicy(extension),
67         _optimizePolicy(extension),
68         _substitutePolicy(extension), _bvhPolicy(extension)
69     {
70     }
71     virtual osgDB::ReaderWriter::ReadResult
72     readNode(const std::string& fileName,
73              const osgDB::Options* opt)
74     {
75         using namespace osg;
76         using namespace osgDB;
77         using osgDB::ReaderWriter;
78 //        Registry* registry = Registry::instance();
79         ref_ptr<osg::Node> optimizedNode = _cachePolicy.find(fileName, opt);
80         if (!optimizedNode.valid()) {
81             std::string otherFileName = _substitutePolicy.substitute(fileName,
82                                                                      opt);
83             ReaderWriter::ReadResult res;
84             if (!otherFileName.empty()) {
85                 res = loadUsingReaderWriter(otherFileName, opt);
86                 if (res.validNode())
87                     optimizedNode = res.getNode();
88             }
89             if (!optimizedNode.valid()) {
90                 res = loadUsingReaderWriter(fileName, opt);
91                 if (!res.validNode())
92                     return res;
93                 ref_ptr<osg::Node> processedNode
94                     = _processPolicy.process(res.getNode(), fileName, opt);
95                 optimizedNode = _optimizePolicy.optimize(processedNode.get(),
96                                                          fileName, opt);
97             }
98             if (opt->getPluginStringData("SimGear::BOUNDINGVOLUMES") != "OFF")
99                 _bvhPolicy.buildBVH(fileName, optimizedNode.get());
100             _cachePolicy.addToCache(fileName, optimizedNode.get());
101         }
102         return ReaderWriter::ReadResult(optimizedNode.get());
103     }
104 protected:
105     static osgDB::ReaderWriter::ReadResult
106     loadUsingReaderWriter(const std::string& fileName,
107                           const osgDB::Options* opt)
108     {
109         using namespace osgDB;
110         ReaderWriter* rw = Registry::instance()
111             ->getReaderWriterForExtension(osgDB::getFileExtension(fileName));
112         if (!rw)
113             return ReaderWriter::ReadResult(); // FILE_NOT_HANDLED
114         return rw->readNode(fileName, opt);
115     }
116     
117     ProcessPolicy _processPolicy;
118     CachePolicy _cachePolicy;
119     OptimizePolicy _optimizePolicy;
120     SubstitutePolicy _substitutePolicy;
121     BVHPolicy _bvhPolicy;
122     virtual ~ModelRegistryCallback() {}
123 };
124
125 // Predefined policies
126
127 struct DefaultProcessPolicy {
128     DefaultProcessPolicy(const std::string& extension) {}
129     osg::Node* process(osg::Node* node, const std::string& filename,
130                        const osgDB::Options* opt);
131 };
132
133 struct DefaultCachePolicy {
134     DefaultCachePolicy(const std::string& extension) {}
135     osg::Node* find(const std::string& fileName,
136                     const osgDB::Options* opt);
137     void addToCache(const std::string& filename, osg::Node* node);
138 };
139
140 struct NoCachePolicy {
141     NoCachePolicy(const std::string& extension) {}
142     osg::Node* find(const std::string& fileName,
143                     const osgDB::Options* opt)
144     {
145         return 0;
146     }
147     void addToCache(const std::string& filename, osg::Node* node) {}
148 };
149
150 class OptimizeModelPolicy {
151 public:
152     OptimizeModelPolicy(const std::string& extension);
153     osg::Node* optimize(osg::Node* node, const std::string& fileName,
154                         const osgDB::Options* opt);
155 protected:
156     unsigned _osgOptions;
157 };
158
159 struct NoOptimizePolicy {
160     NoOptimizePolicy(const std::string& extension) {}
161     osg::Node* optimize(osg::Node* node, const std::string& fileName,
162                         const osgDB::Options* opt)
163     {
164         return node;
165     }
166 };
167
168 struct OSGSubstitutePolicy {
169     OSGSubstitutePolicy(const std::string& extension) {}
170     std::string substitute(const std::string& name,
171                            const osgDB::Options* opt);
172 };
173
174 struct NoSubstitutePolicy {
175     NoSubstitutePolicy(const std::string& extension) {}
176     std::string substitute(const std::string& name,
177                            const osgDB::Options* opt)
178     {
179         return std::string();
180     }
181 };
182
183 struct BuildLeafBVHPolicy {
184     BuildLeafBVHPolicy(const std::string& extension) {}
185     void buildBVH(const std::string& fileName, osg::Node* node);
186 };
187
188 struct BuildGroupBVHPolicy {
189     BuildGroupBVHPolicy(const std::string& extension) {}
190     void buildBVH(const std::string& fileName, osg::Node* node);
191 };
192
193 struct NoBuildBVHPolicy {
194     NoBuildBVHPolicy(const std::string& extension) {}
195     void buildBVH(const std::string& fileName, osg::Node* node);
196 };
197
198 typedef ModelRegistryCallback<DefaultProcessPolicy, DefaultCachePolicy,
199                               OptimizeModelPolicy,
200                               OSGSubstitutePolicy, BuildLeafBVHPolicy>
201 DefaultCallback;
202
203 // The manager for the callbacks
204 class ModelRegistry : public osgDB::Registry::ReadFileCallback,
205                       public ReferencedSingleton<ModelRegistry> {
206 public:
207     ModelRegistry();
208     virtual osgDB::ReaderWriter::ReadResult
209     readImage(const std::string& fileName,
210               const osgDB::Options* opt);
211     virtual osgDB::ReaderWriter::ReadResult
212     readNode(const std::string& fileName,
213              const osgDB::Options* opt);
214     void addImageCallbackForExtension(const std::string& extension,
215                                       osgDB::Registry::ReadFileCallback*
216                                       callback);
217     void addNodeCallbackForExtension(const std::string& extension,
218                                      osgDB::Registry::ReadFileCallback*
219                                      callback);
220     virtual ~ModelRegistry() {}
221 protected:
222     typedef std::map<std::string, osg::ref_ptr<osgDB::Registry::ReadFileCallback> >
223     CallbackMap;
224     CallbackMap imageCallbackMap;
225     CallbackMap nodeCallbackMap;
226     osg::ref_ptr<DefaultCallback> _defaultCallback;
227 };
228
229 // Callback that only loads the file without any caching or
230 // postprocessing.
231 typedef ModelRegistryCallback<DefaultProcessPolicy, NoCachePolicy,
232                               NoOptimizePolicy,
233                               NoSubstitutePolicy, BuildLeafBVHPolicy>
234 LoadOnlyCallback;
235
236 // Proxy for registering extension-based callbacks
237
238 template<typename T>
239 class ModelRegistryCallbackProxy
240 {
241 public:
242     ModelRegistryCallbackProxy(std::string extension)
243     {
244         ModelRegistry::instance()
245             ->addNodeCallbackForExtension(extension, new T(extension));
246     }
247 };
248 }
249 #endif // _SG_MODELREGISTRY_HXX