]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/tgdb/SGTexturedTriangleBin.hxx
Replace SG_USE_STD() by using std::
[simgear.git] / simgear / scene / tgdb / SGTexturedTriangleBin.hxx
index a2ff327b9dbf61d86f46bdc3117dd2b3376b9e6c..bbeb6244c518e207fe19b616f0004693b1c90cf1 100644 (file)
@@ -30,6 +30,8 @@
 #include <simgear/math/SGMath.hxx>
 #include "SGTriangleBin.hxx"
 
+
+
 struct SGVertNormTex {
   SGVertNormTex()
   { }
@@ -54,15 +56,57 @@ struct SGVertNormTex {
   SGVec2f texCoord;
 };
 
+// Use a DrawElementsUShort if there are few enough vertices,
+// otherwise fallback to DrawElementsUInt. Hide the differences
+// between the two from the rest of the code.
+//
+// We don't bother with DrawElementsUByte because that is generally
+// not an advantage on modern hardware.
+class DrawElementsFacade {
+public:
+    DrawElementsFacade(unsigned numVerts) :
+        _ushortElements(0), _uintElements(0)
+    {
+        if (numVerts > 65535)
+            _uintElements
+                = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
+        else
+            _ushortElements
+                = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
+    }
+    
+    void push_back(unsigned val)
+    {
+        if (_uintElements)
+            _uintElements->push_back(val);
+        else
+            _ushortElements->push_back(val);
+    }
+
+    osg::DrawElements* getDrawElements()
+    {
+        if (_uintElements)
+            return _uintElements;
+        return _ushortElements;
+    }
+protected:
+    osg::DrawElementsUShort* _ushortElements;
+    osg::DrawElementsUInt* _uintElements;
+};
+
 class SGTexturedTriangleBin : public SGTriangleBin<SGVertNormTex> {
 public:
+  SGTexturedTriangleBin()
+  {
+    mt_init(&seed, 123);
+  }
 
   // Computes and adds random surface points to the points list.
   // The random points are computed with a density of (coverage points)/1
   // The points are offsetted away from the triangles in
   // offset * positive normal direction.
   void addRandomSurfacePoints(float coverage, float offset,
-                              std::vector<SGVec3f>& points) const
+                              std::vector<SGVec3f>& points)
   {
     unsigned num = getNumTriangles();
     for (unsigned i = 0; i < num; ++i) {
@@ -80,13 +124,13 @@ public:
       // For partial units of area, use a zombie door method to
       // create the proper random chance of a light being created
       // for this triangle
-      float unit = area + sg_random()*coverage;
+      float unit = area + mt_rand(&seed)*coverage;
       
       SGVec3f offsetVector = offset*normalize(normal);
       // generate a light point for each unit of area
       while ( coverage < unit ) {
-        float a = sg_random();
-        float b = sg_random();
+        float a = mt_rand(&seed);
+        float b = mt_rand(&seed);
         if ( a + b > 1 ) {
           a = 1 - a;
           b = 1 - b;
@@ -98,6 +142,43 @@ public:
       }
     }
   }
+  
+   void addRandomPoints(float coverage, 
+                        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 an object being created
+      // for this triangle.
+      double num = area / coverage + mt_rand(&seed);
+
+      // place an object each unit of area
+      while ( num > 1.0 ) {
+        float a = mt_rand(&seed);
+        float b = mt_rand(&seed);
+        if ( a + b > 1 ) {
+          a = 1 - a;
+          b = 1 - b;
+        }
+        float c = 1 - a - b;
+        SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
+        points.push_back(randomPoint);
+        num -= 1.0;
+      }
+    }
+  }
 
   osg::Geometry* buildGeometry(const TriangleVector& triangles) const
   {
@@ -123,9 +204,8 @@ public:
 
     const unsigned invalid = ~unsigned(0);
     std::vector<unsigned> indexMap(getNumVertices(), invalid);
-    
-    osg::DrawElementsUInt* drawElements;
-    drawElements = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
+
+    DrawElementsFacade deFacade(vertices->size());
     for (index_type i = 0; i < triangles.size(); ++i) {
       triangle_ref triangle = triangles[i];
       if (indexMap[triangle[0]] == invalid) {
@@ -134,7 +214,7 @@ public:
         normals->push_back(getVertex(triangle[0]).normal.osg());
         texCoords->push_back(getVertex(triangle[0]).texCoord.osg());
       }
-      drawElements->push_back(indexMap[triangle[0]]);
+      deFacade.push_back(indexMap[triangle[0]]);
 
       if (indexMap[triangle[1]] == invalid) {
         indexMap[triangle[1]] = vertices->size();
@@ -142,7 +222,7 @@ public:
         normals->push_back(getVertex(triangle[1]).normal.osg());
         texCoords->push_back(getVertex(triangle[1]).texCoord.osg());
       }
-      drawElements->push_back(indexMap[triangle[1]]);
+      deFacade.push_back(indexMap[triangle[1]]);
 
       if (indexMap[triangle[2]] == invalid) {
         indexMap[triangle[2]] = vertices->size();
@@ -150,15 +230,19 @@ public:
         normals->push_back(getVertex(triangle[2]).normal.osg());
         texCoords->push_back(getVertex(triangle[2]).texCoord.osg());
       }
-      drawElements->push_back(indexMap[triangle[2]]);
+      deFacade.push_back(indexMap[triangle[2]]);
     }
-    geometry->addPrimitiveSet(drawElements);
+    geometry->addPrimitiveSet(deFacade.getDrawElements());
 
     return geometry;
   }
 
   osg::Geometry* buildGeometry() const
   { return buildGeometry(getTriangles()); }
+
+private:
+  // Random seed for the triangle.
+  mt seed;
 };
 
 #endif