X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Ftgdb%2FSGTexturedTriangleBin.hxx;h=bbeb6244c518e207fe19b616f0004693b1c90cf1;hb=d4c7e950927b1e19a7a7622a7919f32233a6b7a8;hp=a2ff327b9dbf61d86f46bdc3117dd2b3376b9e6c;hpb=560c100484e3678770c9589e6067d627ec5554e5;p=simgear.git diff --git a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx index a2ff327b..bbeb6244 100644 --- a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx +++ b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx @@ -30,6 +30,8 @@ #include #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 { 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& points) const + std::vector& 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& 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 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