00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef SimGear_BoundingVolumeBuildVisitor_hxx
00020 #define SimGear_BoundingVolumeBuildVisitor_hxx
00021
00022 #include <osg/Camera>
00023 #include <osg/Drawable>
00024 #include <osg/Geode>
00025 #include <osg/Group>
00026 #include <osg/PagedLOD>
00027 #include <osg/Transform>
00028 #include <osg/TriangleFunctor>
00029
00030 #include <simgear/scene/material/mat.hxx>
00031 #include <simgear/scene/material/matlib.hxx>
00032 #include <simgear/scene/util/SGNodeMasks.hxx>
00033 #include <simgear/scene/util/SGSceneUserData.hxx>
00034 #include <simgear/math/SGGeometry.hxx>
00035
00036 #include <simgear/scene/bvh/BVHStaticGeometryBuilder.hxx>
00037
00038 namespace simgear {
00039
00040 class BoundingVolumeBuildVisitor : public osg::NodeVisitor {
00041 public:
00042 class PFunctor : public osg::PrimitiveFunctor {
00043 public:
00044 PFunctor() :
00045 _modeCache(0)
00046 {
00047 _geometryBuilder = new BVHStaticGeometryBuilder;
00048 }
00049 virtual ~PFunctor()
00050 { }
00051
00052 virtual void setVertexArray(unsigned int count, const osg::Vec2* vertices)
00053 {
00054 _vertices.resize(count);
00055 for (unsigned i = 0; i < count; ++i)
00056 _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], 0);
00057 }
00058
00059 virtual void setVertexArray(unsigned int count, const osg::Vec3* vertices)
00060 {
00061 _vertices.resize(count);
00062 for (unsigned i = 0; i < count; ++i)
00063 _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], vertices[i][2]);
00064 }
00065
00066 virtual void setVertexArray(unsigned int count, const osg::Vec4* vertices)
00067 {
00068 _vertices.resize(count);
00069 for (unsigned i = 0; i < count; ++i)
00070 _vertices[i] = SGVec3f(vertices[i][0]/vertices[i][3],
00071 vertices[i][1]/vertices[i][3],
00072 vertices[i][2]/vertices[i][3]);
00073 }
00074
00075 virtual void setVertexArray(unsigned int count, const osg::Vec2d* vertices)
00076 {
00077 _vertices.resize(count);
00078 for (unsigned i = 0; i < count; ++i)
00079 _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], 0);
00080 }
00081
00082 virtual void setVertexArray(unsigned int count, const osg::Vec3d* vertices)
00083 {
00084 _vertices.resize(count);
00085 for (unsigned i = 0; i < count; ++i)
00086 _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], vertices[i][2]);
00087 }
00088
00089 virtual void setVertexArray(unsigned int count, const osg::Vec4d* vertices)
00090 {
00091 _vertices.resize(count);
00092 for (unsigned i = 0; i < count; ++i)
00093 _vertices[i] = SGVec3f(vertices[i][0]/vertices[i][3],
00094 vertices[i][1]/vertices[i][3],
00095 vertices[i][2]/vertices[i][3]);
00096 }
00097
00098 virtual void drawArrays(GLenum mode, GLint first, GLsizei count)
00099 {
00100 if (_vertices.empty() || count <= 0)
00101 return;
00102
00103 GLsizei end = first + count;
00104 switch(mode) {
00105 case (GL_TRIANGLES):
00106 for (GLsizei i = first; i < end - 2; i += 3) {
00107 addTriangle(i, i + 1, i + 2);
00108 }
00109 break;
00110
00111 case (GL_TRIANGLE_STRIP):
00112 for (GLsizei i = first; i < end - 2; ++i) {
00113 addTriangle(i, i + 1, i + 2);
00114 }
00115 break;
00116
00117 case (GL_QUADS):
00118 for (GLsizei i = first; i < end - 3; i += 4) {
00119 addQuad(i, i + 1, i + 2, i + 3);
00120 }
00121 break;
00122
00123 case (GL_QUAD_STRIP):
00124 for (GLsizei i = first; i < end - 3; i += 2) {
00125 addQuad(i, i + 1, i + 2, i + 3);
00126 }
00127 break;
00128
00129 case (GL_POLYGON):
00130 case (GL_TRIANGLE_FAN):
00131 for (GLsizei i = first; i < end - 2; ++i) {
00132 addTriangle(first, i + 1, i + 2);
00133 }
00134 break;
00135
00136 case (GL_POINTS):
00137 for (GLsizei i = first; i < end; ++i) {
00138 addPoint(i);
00139 }
00140 break;
00141
00142 case (GL_LINES):
00143 for (GLsizei i = first; i < end - 1; i += 2) {
00144 addLine(i, i + 1);
00145 }
00146 break;
00147
00148 case (GL_LINE_STRIP):
00149 for (GLsizei i = first; i < end - 1; ++i) {
00150 addLine(i, i + 1);
00151 }
00152 break;
00153
00154 case (GL_LINE_LOOP):
00155 for (GLsizei i = first; i < end - 1; ++i) {
00156 addLine(i, i + 1);
00157 }
00158 addLine(end - 1, first);
00159 break;
00160
00161 default:
00162 break;
00163 }
00164 }
00165
00166 virtual void drawElements(GLenum mode, GLsizei count, const GLubyte* indices)
00167 {
00168 drawElementsTemplate(mode, count, indices);
00169 }
00170
00171 virtual void drawElements(GLenum mode, GLsizei count, const GLushort* indices)
00172 {
00173 drawElementsTemplate(mode, count, indices);
00174 }
00175
00176 virtual void drawElements(GLenum mode, GLsizei count, const GLuint* indices)
00177 {
00178 drawElementsTemplate(mode, count, indices);
00179 }
00180
00181 virtual void begin(GLenum mode)
00182 {
00183 _modeCache = mode;
00184 _vertices.resize(0);
00185 }
00186
00187 virtual void vertex(const osg::Vec2& v)
00188 {
00189 _vertices.push_back(SGVec3f(v[0], v[1], 0));
00190 }
00191 virtual void vertex(const osg::Vec3& v)
00192 {
00193 _vertices.push_back(SGVec3f(v[0], v[1], v[2]));
00194 }
00195 virtual void vertex(const osg::Vec4& v)
00196 {
00197 _vertices.push_back(SGVec3f(v[0]/v[3], v[1]/v[3], v[2]/v[3]));
00198 }
00199 virtual void vertex(float x, float y)
00200 {
00201 _vertices.push_back(SGVec3f(x, y, 0));
00202 }
00203 virtual void vertex(float x, float y, float z)
00204 {
00205 _vertices.push_back(SGVec3f(x, y, z));
00206 }
00207 virtual void vertex(float x, float y, float z, float w)
00208 {
00209 _vertices.push_back(SGVec3f(x/w, y/w, z/w));
00210 }
00211 virtual void end()
00212 {
00213 if (_vertices.empty())
00214 return;
00215
00216 drawArrays(_modeCache, 0, _vertices.size());
00217 }
00218
00219 template<typename index_type>
00220 void drawElementsTemplate(GLenum mode, GLsizei count,
00221 const index_type* indices)
00222 {
00223 if (_vertices.empty() || indices == 0 || count <= 0)
00224 return;
00225
00226 switch(mode) {
00227 case (GL_TRIANGLES):
00228 for (GLsizei i = 0; i < count - 2; i += 3) {
00229 addTriangle(indices[i], indices[i + 1], indices[i + 2]);
00230 }
00231 break;
00232
00233 case (GL_TRIANGLE_STRIP):
00234 for (GLsizei i = 0; i < count - 2; ++i) {
00235 addTriangle(indices[i], indices[i + 1], indices[i + 2]);
00236 }
00237 break;
00238
00239 case (GL_QUADS):
00240 for (GLsizei i = 0; i < count - 3; i += 4) {
00241 addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
00242 }
00243 break;
00244
00245 case (GL_QUAD_STRIP):
00246 for (GLsizei i = 0; i < count - 3; i += 2) {
00247 addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
00248 }
00249 break;
00250
00251 case (GL_POLYGON):
00252 case (GL_TRIANGLE_FAN):
00253 for (GLsizei i = 0; i < count - 2; ++i) {
00254 addTriangle(indices[0], indices[i + 1], indices[i + 2]);
00255 }
00256 break;
00257
00258 case (GL_POINTS):
00259 for(GLsizei i = 0; i < count; ++i) {
00260 addPoint(indices[i]);
00261 }
00262 break;
00263
00264 case (GL_LINES):
00265 for (GLsizei i = 0; i < count - 1; i += 2) {
00266 addLine(indices[i], indices[i + 1]);
00267 }
00268 break;
00269
00270 case (GL_LINE_STRIP):
00271 for (GLsizei i = 0; i < count - 1; ++i) {
00272 addLine(indices[i], indices[i + 1]);
00273 }
00274 break;
00275
00276 case (GL_LINE_LOOP):
00277 for (GLsizei i = 0; i < count - 1; ++i) {
00278 addLine(indices[i], indices[i + 1]);
00279 }
00280 addLine(indices[count - 1], indices[0]);
00281 break;
00282
00283 default:
00284 break;
00285 }
00286 }
00287
00288 void addPoint(unsigned i1)
00289 {
00290 addPoint(_vertices[i1]);
00291 }
00292 void addLine(unsigned i1, unsigned i2)
00293 {
00294 addLine(_vertices[i1], _vertices[i2]);
00295 }
00296 void addTriangle(unsigned i1, unsigned i2, unsigned i3)
00297 {
00298 addTriangle(_vertices[i1], _vertices[i2], _vertices[i3]);
00299 }
00300 void addQuad(unsigned i1, unsigned i2, unsigned i3, unsigned i4)
00301 {
00302 addQuad(_vertices[i1], _vertices[i2], _vertices[i3], _vertices[i4]);
00303 }
00304
00305 void addPoint(const SGVec3f& v1)
00306 {
00307 }
00308 void addLine(const SGVec3f& v1, const SGVec3f& v2)
00309 {
00310 }
00311 void addTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
00312 {
00313 _geometryBuilder->addTriangle(v1, v2, v3);
00314 }
00315 void addQuad(const SGVec3f& v1, const SGVec3f& v2,
00316 const SGVec3f& v3, const SGVec3f& v4)
00317 {
00318 _geometryBuilder->addTriangle(v1, v2, v3);
00319 _geometryBuilder->addTriangle(v1, v3, v4);
00320 }
00321
00322 BVHNode* buildTreeAndClear()
00323 {
00324 BVHNode* bvNode = _geometryBuilder->buildTree();
00325 _geometryBuilder = new BVHStaticGeometryBuilder;
00326 _vertices.clear();
00327 return bvNode;
00328 }
00329
00330 void swap(PFunctor& primitiveFunctor)
00331 {
00332 _vertices.swap(primitiveFunctor._vertices);
00333 std::swap(_modeCache, primitiveFunctor._modeCache);
00334 std::swap(_geometryBuilder, primitiveFunctor._geometryBuilder);
00335 }
00336
00337 void setCurrentMaterial(const SGMaterial* material)
00338 {
00339 _geometryBuilder->setCurrentMaterial(material);
00340 }
00341 const SGMaterial* getCurrentMaterial() const
00342 {
00343 return _geometryBuilder->getCurrentMaterial();
00344 }
00345
00346 std::vector<SGVec3f> _vertices;
00347 GLenum _modeCache;
00348
00349 SGSharedPtr<BVHStaticGeometryBuilder> _geometryBuilder;
00350 };
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 BoundingVolumeBuildVisitor(bool dumpIntoLeafs) :
00378 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
00379 _dumpIntoLeafs(dumpIntoLeafs)
00380 {
00381 setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
00382 }
00383 ~BoundingVolumeBuildVisitor()
00384 {
00385 }
00386
00387 const SGMaterial* pushMaterial(osg::Geode* geode)
00388 {
00389 const SGMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
00390 const SGMaterial* material = SGMaterialLib::findMaterial(geode);
00391 if (material)
00392 _primitiveFunctor.setCurrentMaterial(material);
00393 return oldMaterial;
00394 }
00395
00396 void fillWith(osg::Drawable* drawable)
00397 {
00398 drawable->accept(_primitiveFunctor);
00399 }
00400
00401 virtual void apply(osg::Geode& geode)
00402 {
00403 if (hasBoundingVolumeTree(geode))
00404 return;
00405
00406 const SGMaterial* oldMaterial = pushMaterial(&geode);
00407
00408 bool flushHere = getNodePath().size() <= 1 || _dumpIntoLeafs;
00409 if (flushHere) {
00410
00411 PFunctor previousPrimitives;
00412 _primitiveFunctor.swap(previousPrimitives);
00413
00414 const SGMaterial* mat = previousPrimitives.getCurrentMaterial();
00415 _primitiveFunctor.setCurrentMaterial(mat);
00416
00417
00418 for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
00419 fillWith(geode.getDrawable(i));
00420
00421
00422 addBoundingVolumeTreeToNode(geode);
00423
00424
00425 _primitiveFunctor.swap(previousPrimitives);
00426 } else {
00427 for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
00428 fillWith(geode.getDrawable(i));
00429 }
00430
00431 _primitiveFunctor.setCurrentMaterial(oldMaterial);
00432 }
00433
00434 virtual void apply(osg::Group& group)
00435 { traverseAndCollect(group); }
00436
00437 virtual void apply(osg::Transform& transform)
00438 { traverseAndDump(transform); }
00439
00440 virtual void apply(osg::PagedLOD&)
00441 {
00442
00443 }
00444
00445 virtual void apply(osg::Camera& camera)
00446 {
00447 if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
00448 return;
00449 traverseAndDump(camera);
00450 }
00451
00452 void traverseAndDump(osg::Node& node)
00453 {
00454 if (hasBoundingVolumeTree(node))
00455 return;
00456
00457
00458 PFunctor previousPrimitives;
00459 _primitiveFunctor.swap(previousPrimitives);
00460
00461 const SGMaterial* mat = previousPrimitives.getCurrentMaterial();
00462 _primitiveFunctor.setCurrentMaterial(mat);
00463
00464
00465 traverse(node);
00466
00467
00468
00469
00470 addBoundingVolumeTreeToNode(node);
00471
00472
00473 _primitiveFunctor.swap(previousPrimitives);
00474 }
00475
00476 void traverseAndCollect(osg::Node& node)
00477 {
00478
00479 if (hasBoundingVolumeTree(node))
00480 return;
00481
00482
00483 if (getNodePath().size() <= 1) {
00484 traverseAndDump(node);
00485 return;
00486 }
00487
00488
00489
00490
00491
00492 traverse(node);
00493 }
00494
00495 void addBoundingVolumeTreeToNode(osg::Node& node)
00496 {
00497
00498 BVHNode* bvNode = _primitiveFunctor.buildTreeAndClear();
00499
00500
00501 if (!bvNode)
00502 return;
00503
00504 SGSceneUserData* userData;
00505 userData = SGSceneUserData::getOrCreateSceneUserData(&node);
00506 userData->setBVHNode(bvNode);
00507 }
00508
00509 bool hasBoundingVolumeTree(osg::Node& node)
00510 {
00511 SGSceneUserData* userData;
00512 userData = SGSceneUserData::getSceneUserData(&node);
00513 if (!userData)
00514 return false;
00515 if (!userData->getBVHNode())
00516 return false;
00517 return true;
00518 }
00519
00520 private:
00521 PFunctor _primitiveFunctor;
00522 bool _dumpIntoLeafs;
00523 };
00524
00525 }
00526
00527 #endif