MeshOptimizers 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSGUTIL_MESHOPTIMIZERS
  14. #define OSGUTIL_MESHOPTIMIZERS 1
  15. #include <set>
  16. #include <vector>
  17. #include <osg/Geode>
  18. #include <osg/Geometry>
  19. #include <osg/NodeVisitor>
  20. #include <osgUtil/Optimizer>
  21. namespace osgUtil
  22. {
  23. // Helper that collects all the unique Geometry objects in a subgraph.
  24. class OSGUTIL_EXPORT GeometryCollector : public BaseOptimizerVisitor
  25. {
  26. public:
  27. GeometryCollector(Optimizer* optimizer,
  28. Optimizer::OptimizationOptions options)
  29. : BaseOptimizerVisitor(optimizer, options) {}
  30. void reset();
  31. void apply(osg::Geometry& geom);
  32. typedef std::set<osg::Geometry*> GeometryList;
  33. GeometryList& getGeometryList() { return _geometryList; };
  34. protected:
  35. GeometryList _geometryList;
  36. };
  37. // Convert geometry that uses DrawArrays to DrawElements i.e.,
  38. // construct a real mesh. This removes duplicate vertices.
  39. class OSGUTIL_EXPORT IndexMeshVisitor : public GeometryCollector
  40. {
  41. public:
  42. IndexMeshVisitor(Optimizer* optimizer = 0)
  43. : GeometryCollector(optimizer, Optimizer::INDEX_MESH), _generateNewIndicesOnAllGeometries(false)
  44. {
  45. }
  46. inline void setGenerateNewIndicesOnAllGeometries(bool b) { _generateNewIndicesOnAllGeometries = b; }
  47. inline bool getGenerateNewIndicesOnAllGeometries() const { return _generateNewIndicesOnAllGeometries; }
  48. void makeMesh(osg::Geometry& geom);
  49. void makeMesh();
  50. protected:
  51. bool _generateNewIndicesOnAllGeometries;
  52. };
  53. // Optimize the triangle order in a mesh for best use of the GPU's
  54. // post-transform cache. This uses Tom Forsyth's algorithm described
  55. // at http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
  56. class OSGUTIL_EXPORT VertexCacheVisitor : public GeometryCollector
  57. {
  58. public:
  59. VertexCacheVisitor(Optimizer* optimizer = 0)
  60. : GeometryCollector(optimizer, Optimizer::VERTEX_POSTTRANSFORM)
  61. {
  62. }
  63. void optimizeVertices(osg::Geometry& geom);
  64. void optimizeVertices();
  65. private:
  66. void doVertexOptimization(osg::Geometry& geom,
  67. std::vector<unsigned>& vertDrawList);
  68. };
  69. // Gather statistics on post-transform cache misses for geometry
  70. class OSGUTIL_EXPORT VertexCacheMissVisitor : public osg::NodeVisitor
  71. {
  72. public:
  73. VertexCacheMissVisitor(unsigned cacheSize = 16);
  74. void reset();
  75. virtual void apply(osg::Geometry& geom);
  76. void doGeometry(osg::Geometry& geom);
  77. unsigned misses;
  78. unsigned triangles;
  79. protected:
  80. const unsigned _cacheSize;
  81. };
  82. // Optimize the use of the GPU pre-transform cache by arranging vertex
  83. // attributes in the order they are used.
  84. class OSGUTIL_EXPORT VertexAccessOrderVisitor : public GeometryCollector
  85. {
  86. struct OrderByPrimitiveMode
  87. {
  88. inline bool operator() (const osg::ref_ptr<osg::PrimitiveSet>& prim1, const osg::ref_ptr<osg::PrimitiveSet>& prim2)
  89. {
  90. if(prim1 && prim2) {
  91. return prim1->getMode() > prim2->getMode();
  92. }
  93. else if(prim1) {
  94. return true;
  95. }
  96. return false;
  97. }
  98. } order_by_primitive_mode;
  99. public:
  100. VertexAccessOrderVisitor(Optimizer* optimizer = 0)
  101. : GeometryCollector(optimizer, Optimizer::VERTEX_PRETRANSFORM)
  102. {
  103. }
  104. void optimizeOrder();
  105. void optimizeOrder(osg::Geometry& geom);
  106. };
  107. class OSGUTIL_EXPORT SharedArrayOptimizer
  108. {
  109. public:
  110. void findDuplicatedUVs(const osg::Geometry& geometry);
  111. void deduplicateUVs(osg::Geometry& geometry);
  112. protected:
  113. std::map<unsigned int, unsigned int> _deduplicateUvs;
  114. }; // SharedArrayOptimizer
  115. inline void optimizeMesh(osg::Node* node)
  116. {
  117. IndexMeshVisitor imv;
  118. node->accept(imv);
  119. imv.makeMesh();
  120. VertexCacheVisitor vcv;
  121. node->accept(vcv);
  122. vcv.optimizeVertices();
  123. VertexAccessOrderVisitor vaov;
  124. node->accept(vaov);
  125. vaov.optimizeOrder();
  126. }
  127. }
  128. #endif