00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
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
00106
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
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 true );
00151 if (entity != 0) {
00152
00153
00154
00155
00156 float ranges[] = {0, _range_m};
00157 ssgRangeSelector * lod = new ssgRangeSelector;
00158 lod->setRanges(ranges, 2);
00159 if (_heading_type == HEADING_BILLBOARD) {
00160
00161
00162
00163
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 );
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 );
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
00225
00226 SGMatModelGroup::SGMatModelGroup (SGPropertyNode * node)
00227 : _range_m(node->getDoubleValue("range-m", 2000))
00228 {
00229
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