]> git.mxchange.org Git - simgear.git/commitdiff
Second trees patch from Stuart Buchanan
authortimoore <timoore>
Thu, 7 Feb 2008 23:00:23 +0000 (23:00 +0000)
committertimoore <timoore>
Thu, 7 Feb 2008 23:00:23 +0000 (23:00 +0000)
Adds random variation of tree texture maps

simgear/scene/material/mat.cxx
simgear/scene/material/mat.hxx
simgear/scene/material/matmodel.cxx
simgear/scene/tgdb/SGReaderWriterBTG.cxx
simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx
simgear/scene/tgdb/ShaderGeometry.cxx
simgear/scene/tgdb/ShaderGeometry.hxx
simgear/scene/tgdb/TreeBin.cxx
simgear/scene/tgdb/TreeBin.hxx
simgear/scene/tgdb/obj.cxx
simgear/scene/tgdb/obj.hxx

index 4257ae2a6a470afb7cd8c88f72653d293698b3f8..6dde0c519b74b77a8c2439ac7aca45f3f7328d78 100644 (file)
@@ -145,6 +145,11 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props
   tree_height = props->getDoubleValue("tree-height-m", 0.0);
   tree_width = props->getDoubleValue("tree-width-m", 0.0);
   tree_range = props->getDoubleValue("tree-range-m", 0.0);
+  tree_varieties = props->getIntValue("tree-varieties", 1);
+
+  SGPath tpath( fg_root );
+  tpath.append(props->getStringValue("tree-texture"));
+  tree_texture = tpath.str();
 
   // surface values for use with ground reactions
   solid = props->getBoolValue("solid", true);
@@ -181,14 +186,6 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props
   for (unsigned int i = 0; i < object_group_nodes.size(); i++)
     object_groups.push_back(new SGMatModelGroup(object_group_nodes[i]));
 
-  vector<SGPropertyNode_ptr> tree_texture_nodes =
-    ((SGPropertyNode *)props)->getChildren("tree-texture");
-  for (unsigned int i = 0; i < tree_texture_nodes.size(); i++) {
-    SGPath tpath( fg_root );
-    tpath.append(tree_texture_nodes[i]->getStringValue());
-    tree_textures.push_back(tpath.str());
-  }
-
   // read glyph table for taxi-/runway-signs
   vector<SGPropertyNode_ptr> glyph_nodes = props->getChildren("glyph");
   for (unsigned int i = 0; i < glyph_nodes.size(); i++) {
index 38cc7c95cc3992d99742bc884b9bb3b3b95ffeaa..96a33a3aba006efc28df33c34e5aa795833130ce 100644 (file)
@@ -177,11 +177,18 @@ public:
   inline double get_tree_range () const { return tree_range; }
   
   /**
-   * Get the list of textures to use for trees in the forest
+   * Get the number of tree varieties available
    *
-   * @return the vector of forest textures to use.
+   * @return the number of different trees defined in the texture strip
    */
-  inline vector<string> get_tree_textures () const { return  tree_textures; }
+  inline int get_tree_varieties () const { return tree_varieties; }
+  
+  /**
+   * Get the texture strip to use for trees
+   *
+   * @return the texture to use for trees.
+   */
+  inline string get_tree_texture () const { return  tree_texture; }
 
   /**
    * Return if the surface material is solid, if it is not solid, a fluid
@@ -309,6 +316,9 @@ private:
   // Width of the tree
   double tree_width;
 
+  // Number of varieties of tree texture
+  int tree_varieties;
+
   // True if the material is solid, false if it is a fluid
   bool solid;
 
@@ -336,8 +346,8 @@ private:
   // taxiway-/runway-sign texture elements
   map<string, SGSharedPtr<SGMaterialGlyph> > glyphs;
   
-  // The list of forest textures, used when creating trees
-  vector<string> tree_textures;
+  // Tree texture, typically a strip of applicable tree textures
+  string tree_texture;
 \f
   ////////////////////////////////////////////////////////////////////
   // Internal constructors and methods.
index 7af83c7595e72b8dd63cb4932fce2bd4e519f871..70850edc2a30fd6e3d50fd9ee2c5908371a8237d 100644 (file)
@@ -263,7 +263,4 @@ SGMatModelGroup::get_object (int index) const
   return _objects[index];
 }
 
-
-
-
 // end of matmodel.cxx
index 828ab0391c1f737399e87c6cbfbeb0f48b9313bc..9c35ce6af60ff64e2437c3ff98b1371bc9e53e47 100644 (file)
@@ -54,15 +54,18 @@ SGReaderWriterBTG::readNode(const std::string& fileName,
     SGMaterialLib* matlib = 0;
     bool calcLights = false;
     bool useRandomObjects = false;
+    bool useRandomVegetation = false;
     const SGReaderWriterBTGOptions* btgOptions
         = dynamic_cast<const SGReaderWriterBTGOptions*>(options);
     if (btgOptions) {
         matlib = btgOptions->getMatlib();
         calcLights = btgOptions->getCalcLights();
         useRandomObjects = btgOptions->getUseRandomObjects();
+        useRandomVegetation = btgOptions->getUseRandomVegetation();
     }
     osg::Node* result = SGLoadBTG(fileName, matlib, calcLights,
-                                  useRandomObjects);
+                                  useRandomObjects,
+                                  useRandomVegetation);
     if (result)
         return result;
     else
index 91a7c2adeb55f38bc73658f01bcf0d566e656148..86174bf20a3da906375e1aab1e03c02f85c2be48 100644 (file)
@@ -24,14 +24,17 @@ public:
     SGReaderWriterBTGOptions() {}
     SGReaderWriterBTGOptions(const std::string& str):
         osgDB::ReaderWriter::Options(str),
-        _matlib(0), _calcLights(false), _useRandomObjects(false)
+        _matlib(0), _calcLights(false),
+        _useRandomObjects(false),
+        _useRandomVegetation(false)
     {}
     
     SGReaderWriterBTGOptions(const SGReaderWriterBTGOptions& options,
             const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
         osgDB::ReaderWriter::Options(options, copyop),
         _matlib(options._matlib), _calcLights(options._calcLights),
-        _useRandomObjects(options._useRandomObjects)
+        _useRandomObjects(options._useRandomObjects),
+        _useRandomVegetation(options._useRandomVegetation)
     {
     }
     SGMaterialLib* getMatlib() const { return _matlib; }
@@ -39,15 +42,21 @@ public:
     bool getCalcLights() const { return _calcLights; }
     void setCalcLights(bool calcLights)  { _calcLights = calcLights; }
     bool getUseRandomObjects() const { return _useRandomObjects; }
+    bool getUseRandomVegetation() const { return _useRandomVegetation; }
     void setUseRandomObjects(bool useRandomObjects)
     {
         _useRandomObjects = useRandomObjects;
     }
+    void setUseRandomVegetation(bool useRandomVegetation)
+    {
+        _useRandomVegetation = useRandomVegetation;
+    }
+
 protected:
     virtual ~SGReaderWriterBTGOptions() {}
     SGMaterialLib* _matlib;
     bool _calcLights;
     bool _useRandomObjects;
-
+    bool _useRandomVegetation;
 };
 #endif
index 7fdf657f05a0c2119f47edc7c377e0252bb7f055..8691f3d09538e0b66d2e15cf3ff0583520db8bd2 100644 (file)
@@ -22,6 +22,7 @@
 #include <osgDB/Registry>
 #include <osgDB/Input>
 #include <osgDB/ParameterOutput>
+#include <simgear/screen/extensions.hxx>
 
 #include "ShaderGeometry.hxx"
 
@@ -32,10 +33,13 @@ namespace simgear
 {
 void ShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
 {
-    for(PositionSizeList::const_iterator itr = _trees.begin();
-        itr != _trees.end();
-        ++itr) {
-        glColor4fv(itr->ptr());
+    osg::State& state = *renderInfo.getState();
+    const Extensions* extensions = getExtensions(state.getContextID(),true);
+
+    for(TreeBin::TreeList::const_iterator t = _trees.begin(); t != _trees.end(); ++t)
+    {
+        extensions->glVertexAttrib1f(1, (float) t->texture_index/varieties);
+        glColor4f(t->position.x(), t->position.y(), t->position.z(), t->scale);
         _geometry->draw(renderInfo);
     }
 }
@@ -44,13 +48,13 @@ BoundingBox ShaderGeometry::computeBound() const
 {
     BoundingBox geom_box = _geometry->getBound();
     BoundingBox bb;
-    for(PositionSizeList::const_iterator itr = _trees.begin();
+    for(TreeBin::TreeList::const_iterator itr = _trees.begin();
         itr != _trees.end();
         ++itr) {
-        bb.expandBy(geom_box.corner(0)*(*itr)[3] +
-                    Vec3((*itr)[0], (*itr)[1], (*itr)[2]));
-        bb.expandBy(geom_box.corner(7)*(*itr)[3] +
-                    Vec3((*itr)[0], (*itr)[1], (*itr)[2]));
+         bb.expandBy(geom_box.corner(0)*itr->scale +
+                     osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() ));
+         bb.expandBy(geom_box.corner(7)*itr->scale +
+                     osg::Vec3( itr->position.x(), itr->position.y(), itr->position.z() ));
     }
     return bb;
 }
@@ -64,7 +68,7 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr)
     if ((fr[0].matchWord("geometry"))) {
         ++fr;
         iteratorAdvanced = true;
-        Drawable* drawable = fr.readDrawable();
+        osg::Drawable* drawable = fr.readDrawable();
         if (drawable) {
             geom._geometry = drawable;
         }
@@ -78,11 +82,15 @@ bool ShaderGeometry_readLocalData(Object& obj, Input& fr)
         iteratorAdvanced = true;
         // skip {
         while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
-            Vec4 v;
+            SGVec3f v;
+            int t;
+            float s;
             if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
-                && fr[2].getFloat(v.z()) && fr[3].getFloat(v.w())) {
+                && fr[2].getFloat(v.z()) && fr[3].getInt(t) && fr[4].getFloat(s)) {
                     fr += 4;
-                    geom._trees.push_back(v);
+                    //SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
+                    //TreeBin::Tree tree = new TreeBin::Tree(v, t, s);
+                    geom._trees.push_back(TreeBin::Tree(v, t, s));
             } else {
                 ++fr;
             }
@@ -100,12 +108,12 @@ bool ShaderGeometry_writeLocalData(const Object& obj, Output& fw)
     fw.indent() << "instances " << geom._trees.size() << std::endl;
     fw.indent() << "{" << std::endl;
     fw.moveIn();
-    for (ShaderGeometry::PositionSizeList::const_iterator iter
+    for (TreeBin::TreeList::const_iterator iter
              = geom._trees.begin();
          iter != geom._trees.end();
          ++iter) {
-        fw.indent() << iter->x() << " " << iter->y() << " " << iter->z() << " "
-                    << iter->w() << std::endl;
+        fw.indent() << iter->position.x() << " " << iter->position.y() << " " << iter->position.z() << " "
+                    << iter->texture_index << " " << iter->scale << std::endl;
     }
     fw.moveOut();
     fw.indent() << "}" << std::endl;
index 99f2c1e00eeaab36cf09a41684f4c0e158aa6b46..9814af28c46bb7da847dca9a3c7cdb94bd0898a9 100644 (file)
@@ -32,6 +32,8 @@
 #include <osg/Vec3>
 #include <osg/Vec4>
 
+#include "TreeBin.hxx"
+
 namespace simgear
 {
 
@@ -42,6 +44,12 @@ class ShaderGeometry : public osg::Drawable
         { 
           setUseDisplayList(false); 
         }
+
+        ShaderGeometry(int v) :
+          varieties(v)
+        { 
+          setUseDisplayList(false); 
+        }
         
         /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
         ShaderGeometry(const ShaderGeometry& ShaderGeometry,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
@@ -60,14 +68,15 @@ class ShaderGeometry : public osg::Drawable
             _geometry = geometry;
         }
         
-    void addTree(const osg::Vec3& position, float scale)
+        void addTree(TreeBin::Tree tree)
         {
-            _trees.push_back(osg::Vec4(position, scale));
+            _trees.push_back(tree);
         }
         
         osg::ref_ptr<osg::Drawable> _geometry;
 
-        PositionSizeList _trees;
+        TreeBin::TreeList _trees;
+        int varieties;
 
     protected:
     
index a97774443545abec937f7b0e69c519c1ec332617..431e31aa8fedd002af2d6d012f0a2633b90eb77a 100644 (file)
@@ -64,7 +64,7 @@ using namespace osg;
 namespace simgear
 {
 
-osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
+osg::Geometry* createOrthQuads(float w, float h, int varieties, const osg::Matrix& rotate)
 {
 
     //const osg::Vec3& pos = osg::Vec3(0.0f,0.0f,0.0f),
@@ -87,14 +87,19 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
     v[6].set( cw,0.0f,h);
     v[7].set(-cw,0.0f,h);
 
+    // The texture coordinate range is not the
+    // entire coordinate space - as the texture
+    // has a number of different trees on it.
+    float tx = 1.0f/varieties;
+
     t[0].set(0.0f,0.0f);
-    t[1].set(1.0f,0.0f);
-    t[2].set(1.0f,1.0f);
+    t[1].set(  tx,0.0f);
+    t[2].set(  tx,1.0f);
     t[3].set(0.0f,1.0f);
 
     t[4].set(0.0f,0.0f);
-    t[5].set(1.0f,0.0f);
-    t[6].set(1.0f,1.0f);
+    t[5].set(  tx,0.0f);
+    t[6].set(  tx,1.0f);
     t[7].set(0.0f,1.0f);
 
     // For now the normal is normal to the quad. If we want to get
@@ -122,10 +127,13 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
 }
 
  static char vertexShaderSource[] = 
+    "varying vec2 texcoord;\n"
     "varying float fogFactor;\n"
+    "attribute float textureIndex;\n"
     "\n"
     "void main(void)\n"
     "{\n"
+    "  texcoord = gl_MultiTexCoord0.st + vec2(textureIndex, 0.0);\n" 
     "  vec3 position = gl_Vertex.xyz * gl_Color.w + gl_Color.xyz;\n"
     "  gl_Position   = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n"
     "  vec3 ecPosition = vec3(gl_ModelViewMatrix * vec4(position, 1.0));\n"
@@ -135,7 +143,7 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
     " vec4 ambientColor = gl_FrontLightModelProduct.sceneColor + gl_LightSource[0].ambient * gl_FrontMaterial.ambient;\n"
     " gl_FrontColor = ambientColor + gl_LightSource[0].diffuse * vec4(diffuse, 1.0);\n"
     " gl_BackColor = ambientColor + gl_LightSource[0].diffuse * vec4(backDiffuse, 1.0)\n;"
-    "  gl_TexCoord[0] = gl_MultiTexCoord0;\n"
+//    "  gl_TexCoord[0] = gl_MultiTexCoord0;\n"
     " float fogCoord = abs(ecPosition.z);\n"
     "  fogFactor = exp( -gl_Fog.density * gl_Fog.density * fogCoord * fogCoord);\n"
     "  fogFactor = clamp(fogFactor, 0.0, 1.0);\n"
@@ -143,13 +151,14 @@ osg::Geometry* createOrthQuads(float w, float h, const osg::Matrix& rotate)
 
 static char fragmentShaderSource[] = 
     "uniform sampler2D baseTexture; \n"
-//        "varying vec3 N;\n"\r
+    "varying vec2 texcoord;\n"
+//        "varying vec3 N;\n"
 //        "varying vec3 v;\n"
     "varying float fogFactor;\n"
     "\n"
     "void main(void) \n"
     "{ \n"
-    "  vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);\n"
+    "  vec4 base = texture2D( baseTexture, texcoord);\n"
     
     "  vec4 finalColor = base * gl_Color;\n"
     "  gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor );\n"
@@ -164,22 +173,23 @@ namespace
 {
 struct MakeTreesLeaf
 {
-    MakeTreesLeaf(float range, Geometry* geometry) :
-        _range(range), _geometry(geometry)
+    MakeTreesLeaf(float range, Geometry* geometry, int varieties) :
+        _range(range), _geometry(geometry), _varieties(varieties)
     {}
     MakeTreesLeaf(const MakeTreesLeaf& rhs) :
-        _range(rhs._range), _geometry(rhs._geometry) {}
+        _range(rhs._range), _geometry(rhs._geometry), _varieties(rhs._varieties) {}
     LOD* operator() () const
     {
         LOD* result = new LOD;
         Geode* geode = new Geode;
-        ShaderGeometry* sg = new ShaderGeometry;
+        ShaderGeometry* sg = new ShaderGeometry(_varieties);
         sg->setGeometry(_geometry);
         geode->addDrawable(sg);
         result->addChild(geode, 0, _range);
         return result;
     }
     float _range;
+    int _varieties;
     Geometry* _geometry;
 };
 
@@ -190,7 +200,7 @@ struct AddTreesLeafObject
         Geode* geode = static_cast<Geode*>(lod->getChild(0));
         ShaderGeometry* sg
             = static_cast<ShaderGeometry*>(geode->getDrawable(0));
-        sg->addTree(tree.position.osg(), tree.height);
+        sg->addTree(tree);
     }
 };
 
@@ -212,22 +222,20 @@ typedef QuadTreeBuilder<LOD*, TreeBin::Tree, MakeTreesLeaf, AddTreesLeafObject,
 osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
 {
     // Set up some shared structures. 
-    // FIXME: Currently we only take the texture, height and width of the first tree in the forest. In the future
-    // we should be able to handle multiple textures etc.    
-    TreeBin::Tree firstTree = forest.getTree(0);
-    
-    osg::Geometry* shared_geometry = createOrthQuads(firstTree.width, 
-                                                     firstTree.height, 
+    osg::Geometry* shared_geometry = createOrthQuads(forest.width, 
+                                                     forest.height, 
+                                                     forest.texture_varieties,
                                                      transform);
+
     ref_ptr<Group> group;
 
     osg::StateSet* stateset = 0;
-    StateSetMap::iterator iter = treeTextureMap.find(firstTree.texture);
+    StateSetMap::iterator iter = treeTextureMap.find(forest.texture);
     if (iter == treeTextureMap.end()) {
         osg::Texture2D *tex = new osg::Texture2D;
         tex->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP );
         tex->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP );
-        tex->setImage(osgDB::readImageFile(firstTree.texture));
+        tex->setImage(osgDB::readImageFile(forest.texture));
 
         static ref_ptr<AlphaFunc> alphaFunc;
         static ref_ptr<Program> program;
@@ -244,6 +252,8 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
             baseTextureSampler = new osg::Uniform("baseTexture", 0);
             Shader* vertex_shader = new Shader(Shader::VERTEX, vertexShaderSource);
             program->addShader(vertex_shader);
+            program->addBindAttribLocation("textureIndex", 1);
+
             Shader* fragment_shader = new Shader(Shader::FRAGMENT,
                                                  fragmentShaderSource);
             program->addShader(fragment_shader);
@@ -260,9 +270,8 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
         stateset->addUniform(baseTextureSampler.get());
         stateset->setMode(GL_VERTEX_PROGRAM_TWO_SIDE, StateAttribute::ON);
         stateset->setAttribute(material.get());
-        // XXX This should really come from a material definition
-        // instead of being hard-coded.
-        treeTextureMap.insert(StateSetMap::value_type(firstTree.texture,
+
+        treeTextureMap.insert(StateSetMap::value_type(forest.texture,
                                                       stateset));
     } else {
         stateset = iter->second.get();
@@ -272,8 +281,9 @@ osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
         ShaderGeometryQuadtree quadtree(GetTreeCoord(Matrix::inverse(transform)),
                                         AddTreesLeafObject(),
                                         SG_TREE_QUAD_TREE_DEPTH,
-                                        MakeTreesLeaf(firstTree.range,
-                                                      shared_geometry));
+                                        MakeTreesLeaf(forest.range,
+                                                      shared_geometry,
+                                                      forest.texture_varieties));
         quadtree.buildQuadTree(forest._trees.begin(), forest._trees.end());
         group = quadtree.getRoot();
     }
index da94313e9763adf634acd7a0e3f4a16764abf9fc..3c7970281005d2e83d1f9bd756aa801b1f19005f 100644 (file)
 #define TREE_BIN_HXX
 
 #include <vector>
+#include <string>
 
 #include <osg/Geometry>
 #include <osg/Group>
 #include <osg/Matrix>
 
-#include <simgear/math/SGVec3.hxx>
+#include <simgear/math/SGMath.hxx>
 
 namespace simgear
 {
 class TreeBin {
 public:
-    struct Tree {
-        Tree(const SGVec3f& p, string t, float h, float w, double r) :
-            position(p), texture(t), height(h), width(w), range(r)
-        { }
-        SGVec3f position;
-        string texture;
-        float height;
-        float width;
-        double range;
-    };
+  struct Tree {
+    Tree(const SGVec3f& p, int t, float s) :
+      position(p), texture_index(t), scale(s)
+    { }
+    SGVec3f position;
+    int texture_index;
+    float scale;
+  };
+
     typedef std::vector<Tree> TreeList;
 
+    int texture_varieties;
+    double range;
+    float height;
+    float width;
+    std::string texture;
+
     void insert(const Tree& t)
     { _trees.push_back(t); }
-    void insert(const SGVec3f& p, string t, float h, float w, double r)
-    { insert(Tree(p, t, h, w, r)); }
+    void insert(const SGVec3f& p, int t, float s)
+    { insert(Tree(p, t, s)); }
 
     unsigned getNumTrees() const
     { return _trees.size(); }
index d319ec4cd80d1f35cdb8c8403d47e26f8ee03d6e..06ec24fc1c74e2ec7d4947cf0e7e72def8c79f51 100644 (file)
@@ -133,7 +133,7 @@ struct SGTileGeometryBin {
       std::string materialName = obj.get_pt_materials()[grp];
       SGMaterial* material = matlib->find(materialName);
       SGVec4f color = getMaterialLightColor(material);
-      
+
       if (3 <= materialName.size() && materialName.substr(0, 3) != "RWY") {
         // Just plain lights. Not something for the runway.
         addPointGeometry(tileLights, obj.get_wgs84_nodes(), color,
@@ -454,11 +454,11 @@ struct SGTileGeometryBin {
   void computeRandomForest(SGMaterialLib* matlib)
   {
     SGMaterialTriangleMap::iterator i;
-        
+
     // generate a repeatable random seed
     mt seed;
     mt_init(&seed, unsigned(586));
-    
+
     for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
       SGMaterial *mat = matlib->find(i->first);
       if (!mat)
@@ -467,24 +467,32 @@ struct SGTileGeometryBin {
       float coverage = mat->get_tree_coverage();
       if (coverage <= 0)
         continue;
-        
-      vector<string> textures = mat->get_tree_textures();
-      
+
+      // Attributes that don't vary by tree
+      randomForest.texture = mat->get_tree_texture();
+      randomForest.range   = mat->get_tree_range();
+      randomForest.width   = mat->get_tree_width();
+      randomForest.height  = mat->get_tree_height();
+      randomForest.texture_varieties = mat->get_tree_varieties();
+
       std::vector<SGVec3f> randomPoints;
       i->second.addRandomSurfacePoints(coverage, 0, randomPoints);
       std::vector<SGVec3f>::iterator j;
-      for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {      
-        int k = (int)(mt_rand(&seed) * textures.size());        
-        if (k == textures.size()) k--;         
-        randomForest.insert(*j, textures[k], mat->get_tree_height(), mat->get_tree_width(), mat->get_tree_range());
+      for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
+
+        // Apply a random scaling factor and texture index.
+        float scale = (mt_rand(&seed) + mt_rand(&seed)) / 2.0f + 0.5f;
+        int v = (int) (mt_rand(&seed) * mat->get_tree_varieties());
+        if (v == mat->get_tree_varieties()) v--;         
+        randomForest.insert(*j, v, scale);
       }
     }
   }
-  
+
   void computeRandomObjects(SGMaterialLib* matlib)
   {
     SGMaterialTriangleMap::iterator i;
-    
+
     // generate a repeatable random seed
     mt seed;
     mt_init(&seed, unsigned(123));
@@ -493,23 +501,23 @@ struct SGTileGeometryBin {
       SGMaterial *mat = matlib->find(i->first);
       if (!mat)
         continue;
-      
+
       int group_count = mat->get_object_group_count();
-      
+
       if (group_count > 0)
-      {      
+      {
         for (int j = 0; j < group_count; j++)
-        {      
+        {
           SGMatModelGroup *object_group =  mat->get_object_group(j);
           int nObjects = object_group->get_object_count();
-          
+
           if (nObjects > 0)
           {
             // For each of the random models in the group, determine an appropriate
             // number of random placements and insert them.
             for (int k = 0; k < nObjects; k++) {
               SGMatModel * object = object_group->get_object(k);
-              
+
               std::vector<SGVec3f> randomPoints;
 
               i->second.addRandomPoints(object->get_coverage_m2(), randomPoints);
@@ -559,7 +567,7 @@ typedef QuadTreeBuilder<osg::LOD*, ModelLOD, MakeQuadLeaf, AddModelLOD,
                         GetModelLODCoord>  RandomObjectsQuadtree;
 
 osg::Node*
-SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects)
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation)
 {
   SGBinObject tile;
   if (!tile.read_bin(path))
@@ -579,13 +587,13 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
   osg::ref_ptr<osg::Group> randomObjects;
   osg::ref_ptr<osg::Group> randomForest;
   osg::Group* terrainGroup = new osg::Group;
-  
+
   osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib);
   if (node)
     terrainGroup->addChild(node);
-    
+
   if (use_random_objects) {
-  
+
     // Simple matrix for used for flipping models that have been oriented
     // with the center of the tile but upside down.
     static const osg::Matrix flip(1,  0,  0, 0,
@@ -618,7 +626,7 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
         // heading rotation if appropriate.
         osg::Matrix mPos = osg::Matrix::translate(obj.position.osg());        
         osg::MatrixTransform* position;
-        
+
         if (obj.model->get_heading_type() == SGMatModel::HEADING_RANDOM) {
           // Rotate the object around the z axis.
           double hdg = mt_rand(&seed) * M_PI * 2;
@@ -631,7 +639,7 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
           position = new osg::MatrixTransform(mAtt * mPos);
         }
 
-        position->addChild(node);        
+        position->addChild(node);
         models.push_back(ModelLOD(position, obj.lod));
       }
       RandomObjectsQuadtree quadtree((GetModelLODCoord(world2Tile)),
@@ -640,13 +648,16 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool
       randomObjects = quadtree.getRoot();
       randomObjects->setName("random objects");
     }
-      
-    // Now add some random forest.
-    tileGeometryBin.computeRandomForest(matlib);
-    
-    if (tileGeometryBin.randomForest.getNumTrees() > 0) {
-      randomForest = createForest(tileGeometryBin.randomForest, mAtt);
-      randomForest->setName("random trees");      
+
+    if (use_random_vegetation)
+    {
+      // Now add some random forest.
+      tileGeometryBin.computeRandomForest(matlib);
+
+      if (tileGeometryBin.randomForest.getNumTrees() > 0) {
+        randomForest = createForest(tileGeometryBin.randomForest, mAtt);
+        randomForest->setName("random trees");
+      }
     } 
   }
 
index f0c3130092bbeb481f098501ba0c74df1e09391d..f35e2b369f9003524e6d118ba812097eb94eb824 100644 (file)
@@ -56,6 +56,6 @@ inline bool SGGenTile( const std::string&, const SGBucket& b,
 }
 
 osg::Node*
-SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects);
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation);
 
 #endif // _SG_OBJ_HXX