]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/matmodel.cxx
Memory leak fixes from Till Busch
[simgear.git] / simgear / scene / material / matmodel.cxx
index 314f1403882dfb02acf0397ea8d4b4999f0a1566..3d58d18ebba003be7a27e5158d110d0a24f34a6b 100644 (file)
 #include <map>
 SG_USING_STD(map);
 
-#include <simgear/compiler.h>
+#include <osg/AlphaFunc>
+#include <osg/Group>
+#include <osg/LOD>
+#include <osg/StateSet>
+#include <osg/Transform>
 
 #ifdef SG_MATH_EXCEPTION_CLASH
 #  include <math.h>
@@ -120,22 +124,6 @@ SGMatModel::get_model_count( SGModelLib *modellib,
   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,
@@ -145,42 +133,83 @@ SGMatModel::load_models ( SGModelLib *modellib,
                                // 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],
+      osg::Node *entity = modellib->load_model( fg_root, _paths[i],
                                                 prop_root, sim_time_sec,
                                                 /*cache_object*/ true );
       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).
+        
+        // Create multiple LoD nodes so instead of all objects
+        // of the same type appearing at once, some appear further
+        // away.
+        //
+        // Very basic hardcoded distribution:
+        // 4 at normal range
+        // 2 at 1.5 times normal range
+        // 1 at 2 time normal range.
+        //
+        // We achieve this by creating the three different LoD
+        // nodes and adding them to the _models list multiple times.
+        
+        osg::LOD * lod1 = new osg::LOD;
+        lod1->setName("Model LOD");
+        lod1->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+        lod1->setRange(0, 0, _range_m);
+        
+        osg::LOD * lod15 = new osg::LOD;
+        lod15->setName("Model LOD - 1.5");
+        lod15->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+        lod15->setRange(0, 0, 1.5 * _range_m);
+
+        osg::LOD * lod2 = new osg::LOD;
+        lod2->setName("Model LOD - 2.0");
+        lod2->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
+        lod2->setRange(0, 0, 2.0 * _range_m);
+        
+        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);
+          
+             lod1->addChild(entity);
+             lod15->addChild(entity);
+             lod2->addChild(entity);
+        } else {
+          lod1->addChild(entity);
+          lod15->addChild(entity);
+          lod2->addChild(entity);
+        }
+      
+        // Vary the distribution of LoDs by adding multiple times.
+        _models.push_back(lod1);
+        _models.push_back(lod1);
+        _models.push_back(lod1);
+        _models.push_back(lod1);
+
+        _models.push_back(lod15);
+        _models.push_back(lod15);
+
+        _models.push_back(lod2);
+
       } 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 *
+osg::Node*
 SGMatModel::get_model( int index,
                        SGModelLib *modellib,
                        const string &fg_root,
@@ -188,10 +217,10 @@ SGMatModel::get_model( int index,
                        double sim_time_sec )
 {
   load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
-  return _models[index];
+  return _models[index].get();
 }
 
-ssgEntity *
+osg::Node*
 SGMatModel::get_random_model( SGModelLib *modellib,
                               const string &fg_root,
                               SGPropertyNode *prop_root,
@@ -202,7 +231,7 @@ SGMatModel::get_random_model( SGModelLib *modellib,
   int index = int(sg_random() * nModels);
   if (index >= nModels)
     index = 0;
-  return _models[index];
+  return _models[index].get();
 }
 
 double
@@ -261,4 +290,6 @@ SGMatModelGroup::get_object (int index) const
 }
 
 
+
+
 // end of matmodel.cxx