1 // materialmgr.cxx -- class to handle material properties
3 // Written by Curtis Olson, started May 1998.
5 // Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 # include <simgear_config.h>
28 #include <simgear/compiler.h>
29 #include <simgear/constants.h>
30 #include <simgear/structure/exception.hxx>
35 #include <osgDB/Registry>
37 #include <simgear/debug/logstream.hxx>
38 #include <simgear/misc/sg_path.hxx>
39 #include <simgear/misc/sgstream.hxx>
40 #include <simgear/props/props.hxx>
41 #include <simgear/props/props_io.hxx>
42 #include <simgear/props/condition.hxx>
43 #include <simgear/scene/tgdb/userdata.hxx>
44 #include <simgear/threads/SGThread.hxx>
45 #include <simgear/threads/SGGuard.hxx>
50 #include "Technique.hxx"
56 class SGMaterialLib::MatLibPrivate
63 SGMaterialLib::SGMaterialLib ( void ) :
68 // Load a library of material properties
69 bool SGMaterialLib::load( const string &fg_root, const string& mpath,
70 SGPropertyNode *prop_root )
72 SGPropertyNode materialblocks;
74 SG_LOG( SG_INPUT, SG_INFO, "Reading materials from " << mpath );
76 readProperties( mpath, &materialblocks );
77 } catch (const sg_exception &ex) {
78 SG_LOG( SG_INPUT, SG_ALERT, "Error reading materials: "
82 osg::ref_ptr<osgDB::Options> options
84 options->setObjectCacheHint(osgDB::Options::CACHE_ALL);
85 options->setDatabasePath(fg_root);
87 simgear::PropertyList blocks = materialblocks.getChildren("region");
88 simgear::PropertyList::const_iterator block_iter = blocks.begin();
90 for (; block_iter != blocks.end(); block_iter++) {
91 SGPropertyNode_ptr node = block_iter->get();
93 // Read name node purely for logging purposes
94 const SGPropertyNode *nameNode = node->getChild("name");
96 SG_LOG( SG_TERRAIN, SG_INFO, "Loading region "
97 << nameNode->getStringValue());
100 // Read list of areas
101 AreaList* arealist = new AreaList;
103 const simgear::PropertyList areas = node->getChildren("area");
104 simgear::PropertyList::const_iterator area_iter = areas.begin();
105 for (; area_iter != areas.end(); area_iter++) {
106 float x1 = area_iter->get()->getFloatValue("lon1", -180.0f);
107 float x2 = area_iter->get()->getFloatValue("lon2", 180.0);
108 float y1 = area_iter->get()->getFloatValue("lat1", -90.0f);
109 float y2 = area_iter->get()->getFloatValue("lat2", 90.0f);
110 SGRect<float> rect = SGRect<float>(
111 std::min<float>(x1, x2),
112 std::min<float>(y1, y2),
115 arealist->push_back(rect);
116 SG_LOG( SG_TERRAIN, SG_INFO, " Area ("
118 << rect.y() << ") width:"
119 << rect.width() << " height:"
123 // Read conditions node
124 const SGPropertyNode *conditionNode = node->getChild("condition");
125 SGSharedPtr<const SGCondition> condition;
127 condition = sgReadCondition(prop_root, conditionNode);
130 // Now build all the materials for this set of areas and conditions
132 const simgear::PropertyList materials = node->getChildren("material");
133 simgear::PropertyList::const_iterator materials_iter = materials.begin();
134 for (; materials_iter != materials.end(); materials_iter++) {
135 const SGPropertyNode *node = materials_iter->get();
136 SGSharedPtr<SGMaterial> m =
137 new SGMaterial(options.get(), node, prop_root, arealist, condition);
139 std::vector<SGPropertyNode_ptr>names = node->getChildren("name");
140 for ( unsigned int j = 0; j < names.size(); j++ ) {
141 string name = names[j]->getStringValue();
142 // cerr << "Material " << name << endl;
143 matlib[name].push_back(m);
145 SG_LOG( SG_TERRAIN, SG_DEBUG, " Loading material "
146 << names[j]->getStringValue() );
154 // find a material record by material name and tile center
155 SGMaterial *SGMaterialLib::find( const string& material, const SGVec2f center ) const
157 SGMaterial *result = NULL;
158 const_material_map_iterator it = matlib.find( material );
160 // We now have a list of materials that match this
161 // name. Find the first one that matches.
162 // We start at the end of the list, as the materials
163 // list is ordered with the smallest regions at the end.
164 material_list::const_reverse_iterator iter = it->second.rbegin();
165 while (iter != it->second.rend()) {
167 if (result->valid(center)) {
177 // find a material record by material name and tile center
178 SGMaterial *SGMaterialLib::find( const string& material, const SGGeod& center ) const
180 SGVec2f c = SGVec2f(center.getLongitudeDeg(), center.getLatitudeDeg());
181 return find(material, c);
184 SGMaterialCache *SGMaterialLib::generateMatCache(SGVec2f center)
186 SGMaterialCache* newCache = new SGMaterialCache();
187 material_map::const_reverse_iterator it = matlib.rbegin();
188 for (; it != matlib.rend(); ++it) {
189 newCache->insert(it->first, find(it->first, center));
195 SGMaterialCache *SGMaterialLib::generateMatCache(SGGeod center)
197 SGVec2f c = SGVec2f(center.getLongitudeDeg(), center.getLatitudeDeg());
198 return SGMaterialLib::generateMatCache(c);
203 SGMaterialLib::~SGMaterialLib ( void ) {
204 SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
207 const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
211 const simgear::EffectGeode* effectGeode;
212 effectGeode = dynamic_cast<const simgear::EffectGeode*>(geode);
215 const simgear::Effect* effect = effectGeode->getEffect();
218 const SGMaterialUserData* userData;
219 userData = dynamic_cast<const SGMaterialUserData*>(effect->getUserData());
222 return userData->getMaterial();
226 SGMaterialCache::SGMaterialCache ( void )
230 // Insertion into the material cache
231 void SGMaterialCache::insert(const std::string& name, SGSharedPtr<SGMaterial> material) {
232 cache[name] = material;
235 // Search of the material cache
236 SGMaterial *SGMaterialCache::find(const string& material) const
238 SGMaterialCache::material_cache::const_iterator it = cache.find(material);
239 if (it == cache.end())
246 SGMaterialCache::~SGMaterialCache ( void ) {
247 SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialCache::~SGMaterialCache() size=" << cache.size());