]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/matmodel.cxx
Random buildings - initial commit.
[simgear.git] / simgear / scene / material / matmodel.cxx
index 314f1403882dfb02acf0397ea8d4b4999f0a1566..2ff665d9c638f6f1c55d2d938e1f7e5da3246504 100644 (file)
 #include <simgear/compiler.h>
 
 #include <map>
-SG_USING_STD(map);
 
-#include <simgear/compiler.h>
 
-#ifdef SG_MATH_EXCEPTION_CLASH
-#  include <math.h>
-#endif
+#include <osg/AlphaFunc>
+#include <osg/Group>
+#include <osg/LOD>
+#include <osg/StateSet>
+#include <osg/Transform>
 
 #include <simgear/debug/logstream.hxx>
+#include <simgear/math/SGMath.hxx>
 #include <simgear/math/sg_random.h>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/sgstream.hxx>
@@ -44,29 +45,9 @@ SG_USING_STD(map);
 
 #include "matmodel.hxx"
 
-\f
-////////////////////////////////////////////////////////////////////////
-// Local static functions.
-////////////////////////////////////////////////////////////////////////
-
-/**
- * Internal method to test whether a file exists.
- *
- * TODO: this should be moved to a SimGear library of local file
- * functions.
- */
-static inline bool
-local_file_exists( const string& path ) {
-    sg_gzifstream in( path );
-    if ( ! in.is_open() ) {
-       return false;
-    } else {
-       return true;
-    }
-}
-
-
-\f
+using namespace simgear;
+using std::string;
+using std::map;\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGMatModel.
 ////////////////////////////////////////////////////////////////////////
@@ -74,6 +55,7 @@ local_file_exists( const string& path ) {
 SGMatModel::SGMatModel (const SGPropertyNode * node, double range_m)
   : _models_loaded(false),
     _coverage_m2(node->getDoubleValue("coverage-m2", 1000000)),
+    _spacing_m(node->getDoubleValue("spacing-m", 20)),
     _range_m(range_m)
 {
                                // Sanity check
@@ -84,7 +66,7 @@ SGMatModel::SGMatModel (const SGPropertyNode * node, double range_m)
   }
 
                                // Note all the model paths
-  vector <SGPropertyNode_ptr> path_nodes = node->getChildren("path");
+  std::vector <SGPropertyNode_ptr> path_nodes = node->getChildren("path");
   for (unsigned int i = 0; i < path_nodes.size(); i++)
     _paths.push_back(path_nodes[i]->getStringValue());
 
@@ -96,6 +78,8 @@ SGMatModel::SGMatModel (const SGPropertyNode * node, double range_m)
     _heading_type = HEADING_BILLBOARD;
   } else if (hdg == "random") {
     _heading_type = HEADING_RANDOM;
+  } else if (hdg == "mask") {
+    _heading_type = HEADING_MASK;
   } else {
     _heading_type = HEADING_FIXED;
     SG_LOG(SG_INPUT, SG_ALERT, "Unknown heading type: " << hdg
@@ -111,98 +95,54 @@ SGMatModel::~SGMatModel ()
 }
 
 int
-SGMatModel::get_model_count( SGModelLib *modellib,
-                             const string &fg_root,
-                             SGPropertyNode *prop_root,
-                             double sim_time_sec )
+SGMatModel::get_model_count( SGPropertyNode *prop_root )
 {
-  load_models( modellib, fg_root, prop_root, sim_time_sec );
+  load_models( prop_root );
   return _models.size();
 }
 
-static void
-setAlphaClampToBranch( ssgBranch *b, float clamp )
-{
-  int nb = b->getNumKids();
-  for (int i = 0; i<nb; i++) {
-    ssgEntity *e = b->getKid(i);
-    if (e->isAKindOf(ssgTypeLeaf())) {
-      ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
-      s->enable( GL_ALPHA_TEST );
-      s->setAlphaClamp( clamp );
-    } else if (e->isAKindOf(ssgTypeBranch())) {
-      setAlphaClampToBranch( (ssgBranch*)e, clamp );
-    }
-  }
-}
-
 inline void
-SGMatModel::load_models ( SGModelLib *modellib,
-                          const string &fg_root,
-                          SGPropertyNode *prop_root,
-                          double sim_time_sec )
+SGMatModel::load_models( SGPropertyNode *prop_root )
 {
                                // Load model only on demand
   if (!_models_loaded) {
     for (unsigned int i = 0; i < _paths.size(); i++) {
-      ssgEntity *entity = modellib->load_model( fg_root, _paths[i],
-                                                prop_root, sim_time_sec,
-                                                /*cache_object*/ true );
+      osg::Node *entity = SGModelLib::loadModel(_paths[i], prop_root);
       if (entity != 0) {
-                                // FIXME: this stuff can be handled
-                                // in the XML wrapper as well (at least,
-                                // the billboarding should be handled
-                                // there).
-       float ranges[] = {0, _range_m};
-       ssgRangeSelector * lod = new ssgRangeSelector;
-        lod->setRanges(ranges, 2);
-       if (_heading_type == HEADING_BILLBOARD) {
+        // FIXME: this stuff can be handled
+        // in the XML wrapper as well (at least,
+        // the billboarding should be handled
+        // there).
+        
+        if (_heading_type == HEADING_BILLBOARD) {
           // if the model is a billboard, it is likely :
           // 1. a branch with only leaves,
           // 2. a tree or a non rectangular shape faked by transparency
           // We add alpha clamp then
-          if ( entity->isAKindOf(ssgTypeBranch()) ) {
-            ssgBranch *b = (ssgBranch *)entity;
-            setAlphaClampToBranch( b, 0.01f );
-          }
-         ssgCutout * cutout = new ssgCutout(false);
-         cutout->addKid(entity);
-         lod->addKid(cutout);
-       } else {
-         lod->addKid(entity);
-       }
-       _models.push_back(lod);
+          osg::StateSet* stateSet = entity->getOrCreateStateSet();
+          osg::AlphaFunc* alphaFunc =
+            new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01f);
+          stateSet->setAttributeAndModes(alphaFunc,
+                                         osg::StateAttribute::OVERRIDE);
+          stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+        } 
+        
+        _models.push_back(entity);
+        
       } else {
-       SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
+        SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
       }
     }
   }
   _models_loaded = true;
 }
 
-ssgEntity *
-SGMatModel::get_model( int index,
-                       SGModelLib *modellib,
-                       const string &fg_root,
-                       SGPropertyNode *prop_root,
-                       double sim_time_sec )
-{
-  load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
-  return _models[index];
-}
-
-ssgEntity *
-SGMatModel::get_random_model( SGModelLib *modellib,
-                              const string &fg_root,
-                              SGPropertyNode *prop_root,
-                              double sim_time_sec )
+osg::Node*
+SGMatModel::get_random_model( SGPropertyNode *prop_root, mt* seed )
 {
-  load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
+  load_models( prop_root ); // comment this out if preloading models
   int nModels = _models.size();
-  int index = int(sg_random() * nModels);
-  if (index >= nModels)
-    index = 0;
-  return _models[index];
+  return _models[mt_rand(seed) * nModels].get();
 }
 
 double
@@ -211,6 +151,29 @@ SGMatModel::get_coverage_m2 () const
   return _coverage_m2;
 }
 
+double SGMatModel::get_range_m() const
+{
+  return _range_m;
+}
+
+double SGMatModel::get_spacing_m() const
+{
+  return _spacing_m;
+}
+
+double SGMatModel::get_randomized_range_m(mt* seed) const
+{
+  double lrand = mt_rand(seed);
+  
+  // Note that the LoD is not completely randomized.
+  // 10% at 2   * range_m
+  // 30% at 1.5 * range_m
+  // 60% at 1   * range_m
+  if (lrand < 0.1) return 2   * _range_m;
+  if (lrand < 0.4) return 1.5 * _range_m;
+  else return _range_m;
+}
+
 SGMatModel::HeadingType
 SGMatModel::get_heading_type () const
 {
@@ -227,7 +190,7 @@ SGMatModelGroup::SGMatModelGroup (SGPropertyNode * node)
   : _range_m(node->getDoubleValue("range-m", 2000))
 {
                                // Load the object subnodes
-  vector<SGPropertyNode_ptr> object_nodes =
+  std::vector<SGPropertyNode_ptr> object_nodes =
     ((SGPropertyNode *)node)->getChildren("object");
   for (unsigned int i = 0; i < object_nodes.size(); i++) {
     const SGPropertyNode * object_node = object_nodes[i];
@@ -260,5 +223,4 @@ SGMatModelGroup::get_object (int index) const
   return _objects[index];
 }
 
-
 // end of matmodel.cxx