]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/tgdb/SGBuildingBin.cxx
Fix a memory leak in random buildings.
[simgear.git] / simgear / scene / tgdb / SGBuildingBin.cxx
index 8c8d4bc5aeae47e94e4320e246743ef6a9c8527f..3000079e52f577a62e4c60ae509a8e4149a1fde7 100644 (file)
@@ -59,8 +59,8 @@
 #include "ShaderGeometry.hxx"
 #include "SGBuildingBin.hxx"
 
-#define SG_BUILDING_QUAD_TREE_DEPTH 3
-#define SG_BUILDING_FADE_OUT_LEVELS 10
+#define SG_BUILDING_QUAD_TREE_DEPTH 2
+#define SG_BUILDING_FADE_OUT_LEVELS 4
 
 using namespace osg;
 
@@ -69,6 +69,7 @@ namespace simgear
   
 typedef std::map<std::string, osg::observer_ptr<osg::StateSet> > BuildingStateSetMap;
 static BuildingStateSetMap statesetmap;
+static int numBuildings;
 
 void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& building)
 {
@@ -78,10 +79,10 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
       
       // Get or create geometry.
       osg::ref_ptr<osg::Geometry> geom;
-      osg::Vec3Array* v = new osg::Vec3Array;
-      osg::Vec2Array* t = new osg::Vec2Array;
-      osg::Vec4Array* c = new osg::Vec4Array; // single value
-      osg::Vec3Array* n = new osg::Vec3Array;            
+      osg::Vec3Array* v;
+      osg::Vec2Array* t;
+      osg::Vec4Array* c;
+      osg::Vec3Array* n;
       
       if (geode->getNumDrawables() == 0) {
         geom = new osg::Geometry;        
@@ -132,80 +133,79 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
       float ch = building.height;
       
       // 0,0,0 is the bottom center of the front
-      // face, e.g. where the front door would be
-      
+      // face, e.g. where the front door would be      
       
       // BASEMENT
       // This exteds 10m below the main section
       // Front face        
-      v->push_back( osg::Vec3( 0,  cw, -10) * transformMat ); // bottom right
-      v->push_back( osg::Vec3( 0, -cw, -10) * transformMat ); // bottom left
-      v->push_back( osg::Vec3( 0, -cw,   0) * transformMat ); // top left
-      v->push_back( osg::Vec3( 0,  cw,   0) * transformMat ); // top right
+      v->push_back( osg::Vec3( 0, -cw, -10) * transformMat ); // bottom right
+      v->push_back( osg::Vec3( 0,  cw, -10) * transformMat ); // bottom left
+      v->push_back( osg::Vec3( 0,  cw,   0) * transformMat ); // top left
+      v->push_back( osg::Vec3( 0, -cw,   0) * transformMat ); // top right
       
       for (int i=0; i<4; ++i)
-        n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
+        n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
       
       // Left face
-      v->push_back( osg::Vec3(  0, -cw, -10) * transformMat ); // bottom right
-      v->push_back( osg::Vec3( cd, -cw, -10) * transformMat ); // bottom left
-      v->push_back( osg::Vec3( cd, -cw,   0) * transformMat ); // top left
-      v->push_back( osg::Vec3(  0, -cw,   0) * transformMat ); // top right
+      v->push_back( osg::Vec3( -cd, -cw, -10) * transformMat ); // bottom right
+      v->push_back( osg::Vec3(   0, -cw, -10) * transformMat ); // bottom left
+      v->push_back( osg::Vec3(   0, -cw,   0) * transformMat ); // top left
+      v->push_back( osg::Vec3( -cd, -cw,   0) * transformMat ); // top right
 
       for (int i=0; i<4; ++i)
         n->push_back( osg::Vec3(0, -1, 0) * rotationMat ); // normal
 
       // Back face
-      v->push_back( osg::Vec3( cd, -cw, -10) * transformMat ); // bottom right
-      v->push_back( osg::Vec3( cd,  cw, -10) * transformMat ); // bottom left
-      v->push_back( osg::Vec3( cd,  cw,   0) * transformMat ); // top left
-      v->push_back( osg::Vec3( cd, -cw,   0) * transformMat ); // top right
+      v->push_back( osg::Vec3( -cd,  cw, -10) * transformMat ); // bottom right
+      v->push_back( osg::Vec3( -cd, -cw, -10) * transformMat ); // bottom left
+      v->push_back( osg::Vec3( -cd, -cw,   0) * transformMat ); // top left
+      v->push_back( osg::Vec3( -cd,  cw,   0) * transformMat ); // top right
       
       for (int i=0; i<4; ++i)
-        n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
+        n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
       
       // Right face
-      v->push_back( osg::Vec3( cd, cw, -10) * transformMat ); // bottom right
-      v->push_back( osg::Vec3(  0, cw, -10) * transformMat ); // bottom left
-      v->push_back( osg::Vec3(  0, cw,   0) * transformMat ); // top left
-      v->push_back( osg::Vec3( cd, cw,   0) * transformMat ); // top right
+      v->push_back( osg::Vec3(   0, cw, -10) * transformMat ); // bottom right
+      v->push_back( osg::Vec3( -cd, cw, -10) * transformMat ); // bottom left
+      v->push_back( osg::Vec3( -cd, cw,   0) * transformMat ); // top left
+      v->push_back( osg::Vec3(   0, cw,   0) * transformMat ); // top right
 
       for (int i=0; i<4; ++i)
         n->push_back( osg::Vec3(0, 1, 0) * rotationMat ); // normal      
       
       // MAIN BODY
       // Front face        
-      v->push_back( osg::Vec3( 0,  cw,  0) * transformMat ); // bottom right
-      v->push_back( osg::Vec3( 0, -cw,  0) * transformMat ); // bottom left
-      v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // top left
-      v->push_back( osg::Vec3( 0,  cw, ch) * transformMat ); // top right
+      v->push_back( osg::Vec3( 0, -cw,  0) * transformMat ); // bottom right
+      v->push_back( osg::Vec3( 0,  cw,  0) * transformMat ); // bottom left
+      v->push_back( osg::Vec3( 0,  cw, ch) * transformMat ); // top left
+      v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // top right
       
       for (int i=0; i<4; ++i)
-        n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
+        n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
       
       // Left face
-      v->push_back( osg::Vec3(  0, -cw,  0) * transformMat ); // bottom right
-      v->push_back( osg::Vec3( cd, -cw,  0) * transformMat ); // bottom left
-      v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // top left
-      v->push_back( osg::Vec3(  0, -cw, ch) * transformMat ); // top right
+      v->push_back( osg::Vec3( -cd, -cw,  0) * transformMat ); // bottom right
+      v->push_back( osg::Vec3(   0, -cw,  0) * transformMat ); // bottom left
+      v->push_back( osg::Vec3(   0, -cw, ch) * transformMat ); // top left
+      v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // top right
 
       for (int i=0; i<4; ++i)
         n->push_back( osg::Vec3(0, -1, 0) * rotationMat ); // normal
 
       // Back face
-      v->push_back( osg::Vec3( cd, -cw,  0) * transformMat ); // bottom right
-      v->push_back( osg::Vec3( cd,  cw,  0) * transformMat ); // bottom left
-      v->push_back( osg::Vec3( cd,  cw, ch) * transformMat ); // top left
-      v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // top right
+      v->push_back( osg::Vec3( -cd,  cw,  0) * transformMat ); // bottom right
+      v->push_back( osg::Vec3( -cd, -cw,  0) * transformMat ); // bottom left
+      v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // top left
+      v->push_back( osg::Vec3( -cd,  cw, ch) * transformMat ); // top right
       
       for (int i=0; i<4; ++i)
-        n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
+        n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
       
       // Right face
-      v->push_back( osg::Vec3( cd, cw,  0) * transformMat ); // bottom right
-      v->push_back( osg::Vec3(  0, cw,  0) * transformMat ); // bottom left
-      v->push_back( osg::Vec3(  0, cw, ch) * transformMat ); // top left
-      v->push_back( osg::Vec3( cd, cw, ch) * transformMat ); // top right
+      v->push_back( osg::Vec3(   0, cw,  0) * transformMat ); // bottom right
+      v->push_back( osg::Vec3( -cd, cw,  0) * transformMat ); // bottom left
+      v->push_back( osg::Vec3( -cd, cw, ch) * transformMat ); // top left
+      v->push_back( osg::Vec3(   0, cw, ch) * transformMat ); // top right
 
       for (int i=0; i<4; ++i)
         n->push_back( osg::Vec3(0, 1, 0) * rotationMat ); // normal
@@ -214,46 +214,46 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
       if (building.pitched) {      
         
         // Front pitched roof
-        v->push_back( osg::Vec3(     0,  cw,   ch) * transformMat ); // bottom right
-        v->push_back( osg::Vec3(     0, -cw,   ch) * transformMat ); // bottom left
-        v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top left
-        v->push_back( osg::Vec3(0.5*cd,  cw, ch+3) * transformMat ); // top right
+        v->push_back( osg::Vec3(    0, -cw,   ch) * transformMat ); // bottom right
+        v->push_back( osg::Vec3(    0,  cw,   ch) * transformMat ); // bottom left
+        v->push_back( osg::Vec3(-0.5*cd,  cw, ch+3) * transformMat ); // top left
+        v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top right
         
         for (int i=0; i<4; ++i)
-          n->push_back( osg::Vec3(-0.707, 0, 0.707) * rotationMat ); // normal
+          n->push_back( osg::Vec3(0.707, 0, 0.707) * rotationMat ); // normal
         
         // Left pitched roof
-        v->push_back( osg::Vec3(     0, -cw,   ch) * transformMat ); // bottom right
-        v->push_back( osg::Vec3(    cd, -cw,   ch) * transformMat ); // bottom left
-        v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top left
-        v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top right
+        v->push_back( osg::Vec3(    -cd, -cw,   ch) * transformMat ); // bottom right
+        v->push_back( osg::Vec3(      0, -cw,   ch) * transformMat ); // bottom left
+        v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top left
+        v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top right
         
         for (int i=0; i<4; ++i)
           n->push_back( osg::Vec3(0, -1, 0) * rotationMat ); // normal
 
         // Back pitched roof
-        v->push_back( osg::Vec3(    cd, -cw,   ch) * transformMat ); // bottom right
-        v->push_back( osg::Vec3(    cd,  cw,   ch) * transformMat ); // bottom left
-        v->push_back( osg::Vec3(0.5*cd,  cw, ch+3) * transformMat ); // top left
-        v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top right
+        v->push_back( osg::Vec3(    -cd,  cw,   ch) * transformMat ); // bottom right
+        v->push_back( osg::Vec3(    -cd, -cw,   ch) * transformMat ); // bottom left
+        v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top left
+        v->push_back( osg::Vec3(-0.5*cd,  cw, ch+3) * transformMat ); // top right
         
         for (int i=0; i<4; ++i)
-          n->push_back( osg::Vec3(0.707, 0, 0.707) * rotationMat ); // normal      
+          n->push_back( osg::Vec3(-0.707, 0, 0.707) * rotationMat ); // normal      
 
         // Right pitched roof
-        v->push_back( osg::Vec3(    cd, cw,   ch) * transformMat ); // bottom right
-        v->push_back( osg::Vec3(     0, cw,   ch) * transformMat ); // bottom left
-        v->push_back( osg::Vec3(0.5*cd, cw, ch+3) * transformMat ); // top left
-        v->push_back( osg::Vec3(0.5*cd, cw, ch+3) * transformMat ); // top right
+        v->push_back( osg::Vec3(      0, cw,   ch) * transformMat ); // bottom right
+        v->push_back( osg::Vec3(    -cd, cw,   ch) * transformMat ); // bottom left
+        v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) * transformMat ); // top left
+        v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) * transformMat ); // top right
         
         for (int i=0; i<4; ++i)
           n->push_back( osg::Vec3(0, 1, 0) * rotationMat ); // normal
       } else {      
         // Top face
-        v->push_back( osg::Vec3(  0,  cw, ch) * transformMat ); // bottom right
-        v->push_back( osg::Vec3(  0, -cw, ch) * transformMat ); // bottom left
-        v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // top left
-        v->push_back( osg::Vec3( cd,  cw, ch) * transformMat ); // top right
+        v->push_back( osg::Vec3(   0, -cw, ch) * transformMat ); // bottom right
+        v->push_back( osg::Vec3(   0,  cw, ch) * transformMat ); // bottom left
+        v->push_back( osg::Vec3( -cd,  cw, ch) * transformMat ); // top left
+        v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // top right
         
         for (int i=0; i<4; ++i)
           n->push_back( osg::Vec3( 0, 0, 1) * rotationMat ); // normal
@@ -269,8 +269,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
         int row = ((int) (mt_rand(&seed) * 1000)) % 5;
         float base_y = (float) row * 16.0 * 3.0 / 1024.0;
         float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
-        float left_x = 0.0f;
-        float right_x = 32.0 / 1024.0 * round((float) building.width / 6.0f);
+        float left_x = 32.0 / 1024.0 * round((float) building.width / 6.0f);
+        float right_x = 0.0f;
         float front_x = 384.0/1024.0;
         float back_x = 384.0/1024.0 + 32.0 / 1024.0 * round((float) building.depth/ 6.0f);
 
@@ -307,8 +307,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
         if (building.pitched) { 
           // Use the entire height of the roof texture
           top_y = base_y + 16.0 * 3.0 / 1024.0;     
-          left_x = 512/1024.0;
-          right_x = 512/1024.0 + 32.0 / 1024.0 * round(building.width / 6.0f);
+          left_x = 512/1024.0 + 32.0 / 1024.0 * round(building.width / 6.0f);
+          right_x = 512/1024.0;
           front_x = 480.0/1024.0;
           back_x = 512.0/1024.0;
           
@@ -337,8 +337,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
           t->push_back( osg::Vec2( front_x, top_y ) ); // top right
         } else {
           // Flat roof
-          left_x = 512.0/1024.0;
-          right_x = 640.0/1024.0;
+          left_x = 640.0/1024.0;
+          right_x = 512.0/1024.0;
           // Use the entire height of the roof texture
           top_y = base_y + 16.0 * 3.0 / 1024.0;    
           
@@ -355,8 +355,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
         int column = ((int) (mt_rand(&seed) * 1000)) % 5;        
         float base_y = 288 / 1024.0;
         float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
-        float left_x = column * 192.0 /1024.0;
-        float right_x = left_x + 32.0 / 1024.0 * round((float) building.width / 10.0f);
+        float left_x = column * 192.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 10.0f);
+        float right_x = column * 192.0 /1024.0;
 
         // BASEMENT - uses the baseline texture
         for (unsigned int i = 0; i < 16; i++) {          
@@ -394,6 +394,7 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
           top_y = 576.0/1024.0;
           left_x = 960.0/1024.0;
           right_x = 1.0;
+          
           // Front
           t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
           t->push_back( osg::Vec2( left_x,  base_y) ); // bottom left
@@ -421,7 +422,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
           // Flat roof
           base_y = 416/1024.0;
           top_y = 576.0/1024.0;
-          right_x = left_x + 32.0 / 1024.0 * 6.0;
+          left_x = column * 192.0 /1024.0;
+          right_x = (column + 1)* 192.0 /1024.0;
           
           t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
           t->push_back( osg::Vec2( left_x,  base_y) ); // bottom left
@@ -435,8 +437,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
         int column = ((int) (mt_rand(&seed) * 1000)) % 8;        
         float base_y = 576 / 1024.0;
         float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
-        float left_x = column * 128.0 /1024.0;
-        float right_x = left_x + 32.0 / 1024.0 * round((float) building.width / 20.0f);
+        float left_x = column * 128.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 20.0f);
+        float right_x = column * 128.0 /1024.0; 
 
         // BASEMENT - uses the baseline texture
         for (unsigned int i = 0; i < 16; i++) {          
@@ -517,6 +519,10 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin
       geode->setDrawable(0, geom);      
 }
 
+typedef std::map<std::string, osg::observer_ptr<Effect> > EffectMap;
+
+static EffectMap buildingEffectMap;
+
 // Helper classes for creating the quad tree
 namespace
 {
@@ -536,17 +542,16 @@ struct MakeBuildingLeaf
         // Create a series of LOD nodes so trees cover decreases slightly
         // gradually with distance from _range to 2*_range
         for (float i = 0.0; i < SG_BUILDING_FADE_OUT_LEVELS; i++)
-        {        
-            //osg::ref_ptr<EffectGeode> geode = new EffectGeode();
-            //geode->setEffect(_effect);
-            osg::ref_ptr<osg::Geode>  geode = new osg::Geode();          
-            result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0)));
+        {   
+            EffectGeode* geode = new EffectGeode;
+            geode->setEffect(_effect.get());
+            result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0)));               
         }
         return result;
     }
     
     float _range;
-    Effect* _effect;
+    ref_ptr<Effect> _effect;
 };
 
 struct AddBuildingLeafObject
@@ -593,12 +598,38 @@ osg::Group* createRandomBuildings(SGBuildingBinList buildings, const osg::Matrix
     static Matrix ident;
     // Set up some shared structures.
     MatrixTransform* mt = new MatrixTransform(transform);
-    Effect* effect = makeEffect("Effects/model-default", true); 
 
     SGBuildingBin* bin = NULL;
       
     BOOST_FOREACH(bin, buildings)
     {      
+        numBuildings = numBuildings + bin->getNumBuildings();
+        SG_LOG(SG_TERRAIN, SG_DEBUG, "Total random buildings generated: " << numBuildings);
+      
+        ref_ptr<Effect> effect;
+        EffectMap::iterator iter = buildingEffectMap.find(bin->texture);
+
+        if ((iter == buildingEffectMap.end())||
+            (!iter->second.lock(effect)))
+        {
+            SGPropertyNode_ptr effectProp = new SGPropertyNode;
+            makeChild(effectProp, "inherits-from")->setStringValue("Effects/building");
+            SGPropertyNode* params = makeChild(effectProp, "parameters");
+            // Main texture - n=0
+            params->getChild("texture", 0, true)->getChild("image", 0, true)
+                ->setStringValue(bin->texture);
+
+            // Light map - n=1
+            params->getChild("texture", 1, true)->getChild("image", 0, true)
+                ->setStringValue(bin->lightMap);
+                
+            effect = makeEffect(effectProp, true, options);
+            if (iter == buildingEffectMap.end())
+                buildingEffectMap.insert(EffectMap::value_type(bin->texture, effect));
+            else
+                iter->second = effect; // update existing, but empty observer
+        }
+      
         // Now, create a quadbuilding for the buildings.            
         BuildingGeometryQuadtree
             quadbuilding(GetBuildingCoord(), AddBuildingLeafObject(),
@@ -615,36 +646,12 @@ osg::Group* createRandomBuildings(SGBuildingBinList buildings, const osg::Matrix
                        BuildingTransformer(transInv));
         quadbuilding.buildQuadTree(rotatedBuildings.begin(), rotatedBuildings.end());
         
-        ref_ptr<Group> group = quadbuilding.getRoot();
-        
-        // Set up the stateset for this building bin and the texture to use.
-        osg::StateSet* stateSet = group->getOrCreateStateSet();
-        const std::string texturename = bin->texture;
-        osg::Texture2D* texture = SGLoadTexture2D(texturename);
-        texture->setWrap(osg::Texture2D::WRAP_S,  osg::Texture2D::CLAMP_TO_EDGE);
-        texture->setWrap(osg::Texture2D::WRAP_T,  osg::Texture2D::CLAMP_TO_EDGE);
-        stateSet->setTextureAttributeAndModes(0, texture);
-                
-        osg::ShadeModel* shadeModel = new osg::ShadeModel;
-        shadeModel->setMode(osg::ShadeModel::FLAT);
-        stateSet->setAttributeAndModes(shadeModel);
-        stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
-        stateSet->setMode(GL_FOG, osg::StateAttribute::ON);
-        stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-        stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
-        stateSet->setMode(GL_BLEND, osg::StateAttribute::OFF);
-        stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
-        stateSet->setAttribute(new osg::CullFace(osg::CullFace::BACK));
-
-        osg::Material* material = new osg::Material;
-        material->setAmbient(osg::Material::FRONT, osg::Vec4(0.3,0.3,0.3,1.0));
-        material->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0,1.0,1.0,1.0));
-        material->setSpecular(osg::Material::FRONT, osg::Vec4(0,0,0,1.0));
-        material->setShininess(osg::Material::FRONT, 0.0);
-        material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
-        stateSet->setAttribute(material);
-        mt->addChild(group);        
-    }
+        ref_ptr<Group> group = quadbuilding.getRoot();        
+        mt->addChild(group);  
+        delete bin;  
+    }        
+    
+    buildings.clear();
     
     return mt;
 }