matmodel.cxx

00001 // matmodel.cxx -- class to handle models tied to a material property
00002 //
00003 // Written by David Megginson, started May 1998.
00004 //
00005 // Copyright (C) 1998 - 2003  Curtis L. Olson  - http://www.flightgear.org/~curt
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License as
00009 // published by the Free Software Foundation; either version 2 of the
00010 // License, or (at your option) any later version.
00011 //
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 // General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020 //
00021 // $Id: matmodel_8cxx-source.html,v 1.12 2007-12-17 15:37:06 curt Exp $
00022 
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #  include <simgear_config.h>
00026 #endif
00027 
00028 #include <simgear/compiler.h>
00029 
00030 #include <map>
00031 SG_USING_STD(map);
00032 
00033 #include <simgear/compiler.h>
00034 
00035 #ifdef SG_MATH_EXCEPTION_CLASH
00036 #  include <math.h>
00037 #endif
00038 
00039 #include <simgear/debug/logstream.hxx>
00040 #include <simgear/math/sg_random.h>
00041 #include <simgear/misc/sg_path.hxx>
00042 #include <simgear/misc/sgstream.hxx>
00043 #include <simgear/scene/model/modellib.hxx>
00044 
00045 #include "matmodel.hxx"
00046 
00047 
00049 // Local static functions.
00051 
00058 static inline bool
00059 local_file_exists( const string& path ) {
00060     sg_gzifstream in( path );
00061     if ( ! in.is_open() ) {
00062         return false;
00063     } else {
00064         return true;
00065     }
00066 }
00067 
00068 
00069 
00071 // Implementation of SGMatModel.
00073 
00074 SGMatModel::SGMatModel (const SGPropertyNode * node, double range_m)
00075   : _models_loaded(false),
00076     _coverage_m2(node->getDoubleValue("coverage-m2", 1000000)),
00077     _range_m(range_m)
00078 {
00079                                 // Sanity check
00080   if (_coverage_m2 < 1000) {
00081     SG_LOG(SG_INPUT, SG_ALERT, "Random object coverage " << _coverage_m2
00082            << " is too small, forcing, to 1000");
00083     _coverage_m2 = 1000;
00084   }
00085 
00086                                 // Note all the model paths
00087   vector <SGPropertyNode_ptr> path_nodes = node->getChildren("path");
00088   for (unsigned int i = 0; i < path_nodes.size(); i++)
00089     _paths.push_back(path_nodes[i]->getStringValue());
00090 
00091                                 // Note the heading type
00092   string hdg = node->getStringValue("heading-type", "fixed");
00093   if (hdg == "fixed") {
00094     _heading_type = HEADING_FIXED;
00095   } else if (hdg == "billboard") {
00096     _heading_type = HEADING_BILLBOARD;
00097   } else if (hdg == "random") {
00098     _heading_type = HEADING_RANDOM;
00099   } else {
00100     _heading_type = HEADING_FIXED;
00101     SG_LOG(SG_INPUT, SG_ALERT, "Unknown heading type: " << hdg
00102            << "; using 'fixed' instead.");
00103   }
00104 
00105   // uncomment to preload models
00106   // load_models();
00107 }
00108 
00109 SGMatModel::~SGMatModel ()
00110 {
00111 }
00112 
00113 int
00114 SGMatModel::get_model_count( SGModelLib *modellib,
00115                              const string &fg_root,
00116                              SGPropertyNode *prop_root,
00117                              double sim_time_sec )
00118 {
00119   load_models( modellib, fg_root, prop_root, sim_time_sec );
00120   return _models.size();
00121 }
00122 
00123 static void
00124 setAlphaClampToBranch( ssgBranch *b, float clamp )
00125 {
00126   int nb = b->getNumKids();
00127   for (int i = 0; i<nb; i++) {
00128     ssgEntity *e = b->getKid(i);
00129     if (e->isAKindOf(ssgTypeLeaf())) {
00130       ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
00131       s->enable( GL_ALPHA_TEST );
00132       s->setAlphaClamp( clamp );
00133     } else if (e->isAKindOf(ssgTypeBranch())) {
00134       setAlphaClampToBranch( (ssgBranch*)e, clamp );
00135     }
00136   }
00137 }
00138 
00139 inline void
00140 SGMatModel::load_models ( SGModelLib *modellib,
00141                           const string &fg_root,
00142                           SGPropertyNode *prop_root,
00143                           double sim_time_sec )
00144 {
00145                                 // Load model only on demand
00146   if (!_models_loaded) {
00147     for (unsigned int i = 0; i < _paths.size(); i++) {
00148       ssgEntity *entity = modellib->load_model( fg_root, _paths[i],
00149                                                 prop_root, sim_time_sec,
00150                                                 /*cache_object*/ true );
00151       if (entity != 0) {
00152                                 // FIXME: this stuff can be handled
00153                                 // in the XML wrapper as well (at least,
00154                                 // the billboarding should be handled
00155                                 // there).
00156         float ranges[] = {0, _range_m};
00157         ssgRangeSelector * lod = new ssgRangeSelector;
00158         lod->setRanges(ranges, 2);
00159         if (_heading_type == HEADING_BILLBOARD) {
00160           // if the model is a billboard, it is likely :
00161           // 1. a branch with only leaves,
00162           // 2. a tree or a non rectangular shape faked by transparency
00163           // We add alpha clamp then
00164           if ( entity->isAKindOf(ssgTypeBranch()) ) {
00165             ssgBranch *b = (ssgBranch *)entity;
00166             setAlphaClampToBranch( b, 0.01f );
00167           }
00168           ssgCutout * cutout = new ssgCutout(false);
00169           cutout->addKid(entity);
00170           lod->addKid(cutout);
00171         } else {
00172           lod->addKid(entity);
00173         }
00174         _models.push_back(lod);
00175       } else {
00176         SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
00177       }
00178     }
00179   }
00180   _models_loaded = true;
00181 }
00182 
00183 ssgEntity *
00184 SGMatModel::get_model( int index,
00185                        SGModelLib *modellib,
00186                        const string &fg_root,
00187                        SGPropertyNode *prop_root,
00188                        double sim_time_sec )
00189 {
00190   load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
00191   return _models[index];
00192 }
00193 
00194 ssgEntity *
00195 SGMatModel::get_random_model( SGModelLib *modellib,
00196                               const string &fg_root,
00197                               SGPropertyNode *prop_root,
00198                               double sim_time_sec )
00199 {
00200   load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
00201   int nModels = _models.size();
00202   int index = int(sg_random() * nModels);
00203   if (index >= nModels)
00204     index = 0;
00205   return _models[index];
00206 }
00207 
00208 double
00209 SGMatModel::get_coverage_m2 () const
00210 {
00211   return _coverage_m2;
00212 }
00213 
00214 SGMatModel::HeadingType
00215 SGMatModel::get_heading_type () const
00216 {
00217   return _heading_type;
00218 }
00219 
00220 
00221 
00223 // Implementation of SGMatModelGroup.
00225 
00226 SGMatModelGroup::SGMatModelGroup (SGPropertyNode * node)
00227   : _range_m(node->getDoubleValue("range-m", 2000))
00228 {
00229                                 // Load the object subnodes
00230   vector<SGPropertyNode_ptr> object_nodes =
00231     ((SGPropertyNode *)node)->getChildren("object");
00232   for (unsigned int i = 0; i < object_nodes.size(); i++) {
00233     const SGPropertyNode * object_node = object_nodes[i];
00234     if (object_node->hasChild("path"))
00235       _objects.push_back(new SGMatModel(object_node, _range_m));
00236     else
00237       SG_LOG(SG_INPUT, SG_ALERT, "No path supplied for object");
00238   }
00239 }
00240 
00241 SGMatModelGroup::~SGMatModelGroup ()
00242 {
00243 }
00244 
00245 double
00246 SGMatModelGroup::get_range_m () const
00247 {
00248   return _range_m;
00249 }
00250 
00251 int
00252 SGMatModelGroup::get_object_count () const
00253 {
00254   return _objects.size();
00255 }
00256 
00257 SGMatModel *
00258 SGMatModelGroup::get_object (int index) const
00259 {
00260   return _objects[index];
00261 }
00262 
00263 
00264 // end of matmodel.cxx

Generated on Mon Dec 17 09:30:54 2007 for SimGear by  doxygen 1.5.1