00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef SG_TEXTURED_TRIANGLE_BIN_HXX
00023 #define SG_TEXTURED_TRIANGLE_BIN_HXX
00024
00025 #include <osg/Array>
00026 #include <osg/Geometry>
00027 #include <osg/PrimitiveSet>
00028
00029 #include <simgear/math/sg_random.h>
00030 #include <simgear/math/SGMath.hxx>
00031 #include "SGTriangleBin.hxx"
00032
00033
00034
00035 struct SGVertNormTex {
00036 SGVertNormTex()
00037 { }
00038 SGVertNormTex(const SGVec3f& v, const SGVec3f& n, const SGVec2f& t) :
00039 vertex(v), normal(n), texCoord(t)
00040 { }
00041 struct less
00042 {
00043 inline bool operator() (const SGVertNormTex& l,
00044 const SGVertNormTex& r) const
00045 {
00046 if (l.vertex < r.vertex) return true;
00047 else if (r.vertex < l.vertex) return false;
00048 else if (l.normal < r.normal) return true;
00049 else if (r.normal < l.normal) return false;
00050 else return l.texCoord < r.texCoord;
00051 }
00052 };
00053
00054 SGVec3f vertex;
00055 SGVec3f normal;
00056 SGVec2f texCoord;
00057 };
00058
00059
00060
00061
00062
00063
00064
00065 class DrawElementsFacade {
00066 public:
00067 DrawElementsFacade(unsigned numVerts) :
00068 _ushortElements(0), _uintElements(0)
00069 {
00070 if (numVerts > 65535)
00071 _uintElements
00072 = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
00073 else
00074 _ushortElements
00075 = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
00076 }
00077
00078 void push_back(unsigned val)
00079 {
00080 if (_uintElements)
00081 _uintElements->push_back(val);
00082 else
00083 _ushortElements->push_back(val);
00084 }
00085
00086 osg::DrawElements* getDrawElements()
00087 {
00088 if (_uintElements)
00089 return _uintElements;
00090 return _ushortElements;
00091 }
00092 protected:
00093 osg::DrawElementsUShort* _ushortElements;
00094 osg::DrawElementsUInt* _uintElements;
00095 };
00096
00097 class SGTexturedTriangleBin : public SGTriangleBin<SGVertNormTex> {
00098 public:
00099 SGTexturedTriangleBin()
00100 {
00101 mt_init(&seed, 123);
00102 }
00103
00104
00105
00106
00107
00108 void addRandomSurfacePoints(float coverage, float offset,
00109 std::vector<SGVec3f>& points)
00110 {
00111 unsigned num = getNumTriangles();
00112 for (unsigned i = 0; i < num; ++i) {
00113 triangle_ref triangleRef = getTriangleRef(i);
00114 SGVec3f v0 = getVertex(triangleRef[0]).vertex;
00115 SGVec3f v1 = getVertex(triangleRef[1]).vertex;
00116 SGVec3f v2 = getVertex(triangleRef[2]).vertex;
00117 SGVec3f normal = cross(v1 - v0, v2 - v0);
00118
00119
00120 float area = 0.5f*length(normal);
00121 if (area <= SGLimitsf::min())
00122 continue;
00123
00124
00125
00126
00127 float unit = area + mt_rand(&seed)*coverage;
00128
00129 SGVec3f offsetVector = offset*normalize(normal);
00130
00131
00132 while ( coverage < unit ) {
00133
00134 float a = mt_rand(&seed);
00135 float b = mt_rand(&seed);
00136
00137 if ( a + b > 1 ) {
00138 a = 1 - a;
00139 b = 1 - b;
00140 }
00141 float c = 1 - a - b;
00142 SGVec3f randomPoint = offsetVector + a*v0 + b*v1 + c*v2;
00143 points.push_back(randomPoint);
00144 unit -= coverage;
00145 }
00146 }
00147 }
00148
00149
00150
00151 void addRandomTreePoints(float wood_coverage,
00152 float tree_density,
00153 float wood_size,
00154 std::vector<SGVec3f>& points)
00155 {
00156 unsigned num = getNumTriangles();
00157 for (unsigned i = 0; i < num; ++i) {
00158 triangle_ref triangleRef = getTriangleRef(i);
00159 SGVec3f v0 = getVertex(triangleRef[0]).vertex;
00160 SGVec3f v1 = getVertex(triangleRef[1]).vertex;
00161 SGVec3f v2 = getVertex(triangleRef[2]).vertex;
00162 SGVec3f normal = cross(v1 - v0, v2 - v0);
00163
00164
00165 float area = 0.5f*length(normal);
00166 if (area <= SGLimitsf::min())
00167 continue;
00168
00169
00170
00171
00172 float unit = area + mt_rand(&seed)*wood_coverage;
00173
00174 int woodcount = (int) (unit / wood_coverage);
00175
00176 for (int j = 0; j < woodcount; j++) {
00177
00178 if (wood_size < area) {
00179
00180
00181
00182 float x = mt_rand(&seed);
00183 float y = mt_rand(&seed);
00184
00185
00186
00187 float ws = wood_size + wood_size * (mt_rand(&seed) - 0.5f);
00188 unsigned total_trees = ws / tree_density;
00189 float wood_length = sqrt(ws);
00190
00191
00192
00193 float x_tree_factor = wood_length / length(v1 -v0);
00194 float y_tree_factor = wood_length / length(v2 -v0);
00195
00196 for (unsigned k = 0; k <= total_trees; k++) {
00197
00198 float a = x + x_tree_factor * (mt_rand(&seed) - 0.5f);
00199 float b = y + y_tree_factor * (mt_rand(&seed) - 0.5f);
00200
00201
00202
00203
00204
00205
00206 if (a < 0.0f || a > 1.0f) a = mt_rand(&seed);
00207 if (b < 0.0f || b > 1.0f) b = mt_rand(&seed);
00208
00209 if ( a + b > 1.0f ) {
00210 a = 1.0f - a;
00211 b = 1.0f - b;
00212 }
00213
00214 float c = 1.0f - a - b;
00215
00216 SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
00217
00218 points.push_back(randomPoint);
00219 }
00220 } else {
00221
00222
00223 unsigned total_trees = area / tree_density;
00224
00225 for (unsigned k = 0; k <= total_trees; k++) {
00226
00227 float a = mt_rand(&seed);
00228 float b = mt_rand(&seed);
00229
00230 if ( a + b > 1.0f ) {
00231 a = 1.0f - a;
00232 b = 1.0f - b;
00233 }
00234
00235 float c = 1.0f - a - b;
00236
00237 SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
00238 points.push_back(randomPoint);
00239 }
00240 }
00241 }
00242 }
00243 }
00244
00245 void addRandomPoints(float coverage,
00246 std::vector<SGVec3f>& points)
00247 {
00248 unsigned num = getNumTriangles();
00249 for (unsigned i = 0; i < num; ++i) {
00250 triangle_ref triangleRef = getTriangleRef(i);
00251 SGVec3f v0 = getVertex(triangleRef[0]).vertex;
00252 SGVec3f v1 = getVertex(triangleRef[1]).vertex;
00253 SGVec3f v2 = getVertex(triangleRef[2]).vertex;
00254 SGVec3f normal = cross(v1 - v0, v2 - v0);
00255
00256
00257 float area = 0.5f*length(normal);
00258 if (area <= SGLimitsf::min())
00259 continue;
00260
00261
00262
00263
00264 double num = area / coverage + mt_rand(&seed);
00265
00266
00267 while ( num > 1.0 ) {
00268 float a = mt_rand(&seed);
00269 float b = mt_rand(&seed);
00270 if ( a + b > 1 ) {
00271 a = 1 - a;
00272 b = 1 - b;
00273 }
00274 float c = 1 - a - b;
00275 SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
00276 points.push_back(randomPoint);
00277 num -= 1.0;
00278 }
00279 }
00280 }
00281
00282 osg::Geometry* buildGeometry(const TriangleVector& triangles) const
00283 {
00284
00285 if (empty() || triangles.empty())
00286 return 0;
00287
00288
00289 osg::Vec3Array* vertices = new osg::Vec3Array;
00290 osg::Vec3Array* normals = new osg::Vec3Array;
00291 osg::Vec2Array* texCoords = new osg::Vec2Array;
00292
00293 osg::Vec4Array* colors = new osg::Vec4Array;
00294 colors->push_back(osg::Vec4(1, 1, 1, 1));
00295
00296 osg::Geometry* geometry = new osg::Geometry;
00297 geometry->setVertexArray(vertices);
00298 geometry->setNormalArray(normals);
00299 geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
00300 geometry->setColorArray(colors);
00301 geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
00302 geometry->setTexCoordArray(0, texCoords);
00303
00304 const unsigned invalid = ~unsigned(0);
00305 std::vector<unsigned> indexMap(getNumVertices(), invalid);
00306
00307 DrawElementsFacade deFacade(vertices->size());
00308 for (index_type i = 0; i < triangles.size(); ++i) {
00309 triangle_ref triangle = triangles[i];
00310 if (indexMap[triangle[0]] == invalid) {
00311 indexMap[triangle[0]] = vertices->size();
00312 vertices->push_back(toOsg(getVertex(triangle[0]).vertex));
00313 normals->push_back(toOsg(getVertex(triangle[0]).normal));
00314 texCoords->push_back(toOsg(getVertex(triangle[0]).texCoord));
00315 }
00316 deFacade.push_back(indexMap[triangle[0]]);
00317
00318 if (indexMap[triangle[1]] == invalid) {
00319 indexMap[triangle[1]] = vertices->size();
00320 vertices->push_back(toOsg(getVertex(triangle[1]).vertex));
00321 normals->push_back(toOsg(getVertex(triangle[1]).normal));
00322 texCoords->push_back(toOsg(getVertex(triangle[1]).texCoord));
00323 }
00324 deFacade.push_back(indexMap[triangle[1]]);
00325
00326 if (indexMap[triangle[2]] == invalid) {
00327 indexMap[triangle[2]] = vertices->size();
00328 vertices->push_back(toOsg(getVertex(triangle[2]).vertex));
00329 normals->push_back(toOsg(getVertex(triangle[2]).normal));
00330 texCoords->push_back(toOsg(getVertex(triangle[2]).texCoord));
00331 }
00332 deFacade.push_back(indexMap[triangle[2]]);
00333 }
00334 geometry->addPrimitiveSet(deFacade.getDrawElements());
00335
00336 return geometry;
00337 }
00338
00339 osg::Geometry* buildGeometry() const
00340 { return buildGeometry(getTriangles()); }
00341
00342 private:
00343
00344 mt seed;
00345 };
00346
00347 #endif