]> git.mxchange.org Git - simgear.git/commitdiff
Stuart Buchanan: I've been working on a small patch to allow trees to be grouped...
authortorsten <torsten>
Sun, 9 Aug 2009 10:49:20 +0000 (10:49 +0000)
committerTim Moore <timoore@redhat.com>
Sun, 9 Aug 2009 21:56:10 +0000 (23:56 +0200)
simgear/scene/material/mat.cxx
simgear/scene/material/mat.hxx
simgear/scene/tgdb/SGTexturedTriangleBin.hxx
simgear/scene/tgdb/obj.cxx

index dc79d094912d6dd3f146c37725875e2271acbba3..2fc7e9c84c3573c09a958419fbff39ca08e21c5a 100644 (file)
@@ -131,11 +131,14 @@ SGMaterial::read_properties(const osgDB::ReaderWriter::Options* options,
   wrapv = props->getBoolValue("wrapv", true);
   mipmap = props->getBoolValue("mipmap", true);
   light_coverage = props->getDoubleValue("light-coverage", 0.0);
-  tree_coverage = props->getDoubleValue("tree-coverage", 0.0);
+  wood_coverage = props->getDoubleValue("wood-coverage", 0.0);
+  wood_size = props->getDoubleValue("wood-size", 0.0);
+  tree_density = props->getDoubleValue("tree-density", 1.0);
   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);
+
   const SGPropertyNode* treeTexNode = props->getChild("tree-texture");
   if (treeTexNode) {
     string treeTexPath = props->getStringValue("tree-texture");
index c510575ed962f887cfeff099085f1c7a413bd4ee..ac2e5f1bb26d6343b708e82a63f56c9e5fed673c 100644 (file)
@@ -131,23 +131,37 @@ public:
   inline double get_light_coverage () const { return light_coverage; }
 
   /**
-   * Get the forest coverage.
+   * Get the wood coverage.
    *
-   * A smaller number means more generated forest canopy.
+   * A smaller number means more generated woods within the forest.
    *
-   * @return The area (m^2) covered by each canopy.
+   * @return The area (m^2) covered by each wood.
    */
-  inline double get_tree_coverage () const { return tree_coverage; }
+  inline double get_wood_coverage () const { return wood_coverage; }
 
   /**
-   * Get the forest height.
+   * Get the density of the wood
+   *
+   * @return The area (m^2) covered by each tree in the wood.
+   */
+  inline double get_tree_density () const { return tree_density; }
+  
+  /**
+   * Get the size of each wood
+   *
+   * @return the average area (m^2) of each wood
+   */
+  inline double get_wood_size () const { return wood_size; }
+  
+  /**
+   * Get the tree height.
    *
    * @return The average height of the trees.
    */
   inline double get_tree_height () const { return tree_height; }
 
   /**
-   * Get the forest width.
+   * Get the tree width.
    *
    * @return The average width of the trees.
    */
@@ -289,9 +303,15 @@ private:
   // coverage of night lighting.
   double light_coverage;
   
-  // coverage of trees
-  double tree_coverage;
-  
+  // coverage of woods
+  double wood_coverage;
+
+  // The size of each wood
+  double wood_size;
+
+  // Tree density within the wood
+  double tree_density;
+
   // Range at which trees become visible
   double tree_range;
 
index bbeb6244c518e207fe19b616f0004693b1c90cf1..96e49776194d2a9545eef585dfd6c37710aa662f 100644 (file)
@@ -128,9 +128,12 @@ public:
       
       SGVec3f offsetVector = offset*normalize(normal);
       // generate a light point for each unit of area
+
       while ( coverage < unit ) {
+
         float a = mt_rand(&seed);
         float b = mt_rand(&seed);
+
         if ( a + b > 1 ) {
           a = 1 - a;
           b = 1 - b;
@@ -142,6 +145,102 @@ public:
       }
     }
   }
+
+  // Computes and adds random surface points to the points list for tree
+  // coverage.
+  void addRandomTreePoints(float wood_coverage, 
+                           float tree_density,
+                           float wood_size,
+                           std::vector<SGVec3f>& points)
+  {
+    unsigned num = getNumTriangles();
+    for (unsigned i = 0; i < num; ++i) {
+      triangle_ref triangleRef = getTriangleRef(i);
+      SGVec3f v0 = getVertex(triangleRef[0]).vertex;
+      SGVec3f v1 = getVertex(triangleRef[1]).vertex;
+      SGVec3f v2 = getVertex(triangleRef[2]).vertex;
+      SGVec3f normal = cross(v1 - v0, v2 - v0);
+      
+      // Compute the area
+      float area = 0.5f*length(normal);
+      if (area <= SGLimitsf::min())
+        continue;
+      
+      // For partial units of area, use a zombie door method to
+      // create the proper random chance of a point being created
+      // for this triangle
+      float unit = area + mt_rand(&seed)*wood_coverage;
+
+      int woodcount = (int) (unit / wood_coverage);
+
+      for (unsigned j = 0; j < woodcount; j++) {
+
+        if (wood_size < area) {
+          // We need to place a wood within the triangle and populate it
+
+          // Determine the center of the wood
+          float x = mt_rand(&seed);
+          float y = mt_rand(&seed);
+
+          // Determine the size of this wood in m^2, and the number
+          // of trees in the wood
+          float ws = wood_size + wood_size * (mt_rand(&seed) - 0.5f);
+          unsigned total_trees = ws / tree_density;
+          float wood_length = sqrt(ws);
+
+          // From our wood size, work out the fraction on the two axis.
+          // This will be used as a factor when placing trees in the wood.
+          float x_tree_factor = wood_length / length(v1 -v0);
+          float y_tree_factor = wood_length / length(v2 -v0);
+
+          for (unsigned k = 0; k <= total_trees; k++) {
+
+            float a = x + x_tree_factor * (mt_rand(&seed) - 0.5f);
+            float b = y + y_tree_factor * (mt_rand(&seed) - 0.5f);
+
+
+            // In some cases, the triangle side lengths are so small that the
+            // tree_factors become so large as to make placing the tree within
+            // the triangle almost impossible. In this case, we place them
+            // randomly across the triangle.
+            if (a < 0.0f || a > 1.0f) a = mt_rand(&seed);
+            if (b < 0.0f || b > 1.0f) b = mt_rand(&seed);
+            
+            if ( a + b > 1.0f ) {
+              a = 1.0f - a;
+              b = 1.0f - b;
+            }
+              
+            float c = 1.0f - a - b;
+
+            SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
+
+            points.push_back(randomPoint);
+          }
+        } else {
+          // This triangle is too small to contain a complete wood, so just
+          // distribute trees across it.
+          unsigned total_trees = area / tree_density;
+
+          for (unsigned k = 0; k <= total_trees; k++) {
+
+            float a = mt_rand(&seed);
+            float b = mt_rand(&seed);
+
+            if ( a + b > 1.0f ) {
+              a = 1.0f - a;
+              b = 1.0f - b;
+            }
+
+            float c = 1.0f - a - b;
+
+            SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
+            points.push_back(randomPoint);
+          }
+        }
+      }
+    }
+  }
   
    void addRandomPoints(float coverage, 
                         std::vector<SGVec3f>& points)
index 3869c521ab2588a369ada417d8b8b4055aac6733..cdfd64f671c227d5151752f49d2349e4f0bb9063 100644 (file)
@@ -455,8 +455,8 @@ struct SGTileGeometryBin {
       if (!mat)
         continue;
 
-      float coverage = mat->get_tree_coverage();
-      if (coverage <= 0)
+      float wood_coverage = mat->get_wood_coverage();
+      if (wood_coverage <= 0)
         continue;
 
       // Attributes that don't vary by tree
@@ -467,7 +467,11 @@ struct SGTileGeometryBin {
       randomForest.texture_varieties = mat->get_tree_varieties();
 
       std::vector<SGVec3f> randomPoints;
-      i->second.addRandomSurfacePoints(coverage, 0, randomPoints);
+      i->second.addRandomTreePoints(wood_coverage,
+                                    mat->get_tree_density(),
+                                    mat->get_wood_size(),
+                                    randomPoints);
+      
       std::vector<SGVec3f>::iterator j;
       for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {