1 // Copyright (C) 2008 Till Busch buti@bux.at
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17 
18 #ifndef _SG_MODEL_LIB_HXX
19 #define _SG_MODEL_LIB_HXX 1
20 
21 #include <simgear/compiler.h>	// for SG_USING_STD
22 
23 #include <map>
24 #include <string>
25 
26 #include <osg/Node>
27 #include <osgDB/ReaderWriter>
28 
29 #include <simgear/props/props.hxx>
30 #include <simgear/misc/sg_path.hxx>
31 
32 namespace osg {
33     class PagedLOD;
34 }
35 
36 namespace simgear {
37 
38 class SGModelData; // defined below
39 class SGModelLOD;  // defined below
40 
41 /**
42  * Class for loading and managing models with XML wrappers.
43  */
44 class SGModelLib
45 {
46 public:
47     typedef osg::Node *(*panel_func)(SGPropertyNode *);
48 
49     static void init(const std::string &root_dir, SGPropertyNode* root);
50 
51     static void resetPropertyRoot();
52 
53     static void setPanelFunc(panel_func pf);
54 
55     // Load a 3D model (any format)
56     // data->modelLoaded() will be called after the model is loaded
57     static osg::Node* loadModel(const std::string &path,
58                                 SGPropertyNode *prop_root = NULL,
59                                 SGModelData *data=0, bool load2DPanels=false);
60 
61     // Load a 3D model (any format) through the DatabasePager.
62     // This function initially just returns a proxy node that refers to
63     // the model file. Once the viewer steps onto that node the
64     // model will be loaded.
65     static osg::Node* loadDeferredModel(const std::string &path,
66                                         SGPropertyNode *prop_root = NULL,
67                                         SGModelData *data=0);
68     // Load a 3D model (any format) through the DatabasePager.
69     // This function initially just returns a PagedLOD node that refers to
70     // the model file. Once the viewer steps onto that node the
71     // model will be loaded. When the viewer does no longer reference this
72     // node for a long time the node is unloaded again.
73     static osg::PagedLOD* loadPagedModel(SGPropertyNode *prop_root,
74                                       SGModelData *data,
75                                       SGModelLOD model_lods);
76     static osg::PagedLOD* loadPagedModel(const std::string &path,
77                                      SGPropertyNode *prop_root = NULL,
78                                      SGModelData *data=0);
79 
80    static osg::PagedLOD* loadPagedModel(std::vector<string> paths,
81                                     SGPropertyNode *prop_root = NULL,
82                                     SGModelData *data=0);
83 
84     static std::string findDataFile(const std::string& file,
85       const osgDB::Options* opts = nullptr,
86       SGPath currentDir = SGPath());
87 
88     static std::string findDataFile(const SGPath& file,
89       const osgDB::Options* opts = nullptr,
90       SGPath currentDir = SGPath());
91 protected:
92     SGModelLib();
93     ~SGModelLib ();
94 
95 private:
96   static SGPropertyNode_ptr static_propRoot;
97   static panel_func static_panelFunc;
98 };
99 
100 
101 /**
102  * Abstract class for adding data to the scene graph.  modelLoaded() is
103  * called after the model was loaded, and the destructor when the branch
104  * is removed from the scene graph.
105  */
106 class SGModelData : public osg::Referenced {
107 public:
~SGModelData()108     virtual ~SGModelData() {}
109     virtual void modelLoaded(const std::string& path, SGPropertyNode *prop,
110                              osg::Node* branch) = 0;
111     virtual SGModelData* clone() const = 0;
112 
113     using ErrorContext = std::map<std::string, std::string>;
114 
115     virtual ErrorContext getErrorContext() const = 0;
116 };
117 
118 /*
119  * Data for a model with multiple LoD versions
120  */
121 
122 class SGModelLOD {
123 public:
124   struct ModelLOD {
ModelLODsimgear::SGModelLOD::ModelLOD125     ModelLOD(const string &p, float minrange, float maxrange) :
126       path(p), min_range(minrange), max_range(maxrange)
127       { }
128     const string &path;
129     float min_range;
130     float max_range;
131   };
132 typedef std::vector<ModelLOD> ModelLODList;
133 
insert(const ModelLOD & model)134 void insert(const ModelLOD& model)
135 {
136   _models.push_back(model);
137 }
138 
insert(const string & p,float minrange,float maxrange)139 void insert(const string &p, float minrange, float maxrange)
140 {
141   insert(ModelLOD(p, minrange, maxrange));
142 }
143 
getNumLODs() const144 unsigned getNumLODs() const { return _models.size(); }
getModelLOD(unsigned i) const145 const ModelLOD& getModelLOD(unsigned i) const { return _models[i]; }
146 
147 private:
148   ModelLODList _models;
149 };
150 
151 }
152 
153 #endif // _SG_MODEL_LIB_HXX
154