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 14#ifndef OSGUTIL_MESHOPTIMIZERS 15#define OSGUTIL_MESHOPTIMIZERS 1 16 17#include <set> 18#include <vector> 19 20#include <osg/Geode> 21#include <osg/Geometry> 22#include <osg/NodeVisitor> 23 24#include <osgUtil/Optimizer> 25 26namespace osgUtil 27{ 28// Helper that collects all the unique Geometry objects in a subgraph. 29class OSGUTIL_EXPORT GeometryCollector : public BaseOptimizerVisitor 30{ 31public: 32 GeometryCollector(Optimizer* optimizer, 33 Optimizer::OptimizationOptions options) 34 : BaseOptimizerVisitor(optimizer, options) {} 35 void reset(); 36 void apply(osg::Geometry& geom); 37 typedef std::set<osg::Geometry*> GeometryList; 38 GeometryList& getGeometryList() { return _geometryList; }; 39protected: 40 GeometryList _geometryList; 41}; 42 43// Convert geometry that uses DrawArrays to DrawElements i.e., 44// construct a real mesh. This removes duplicate vertices. 45class OSGUTIL_EXPORT IndexMeshVisitor : public GeometryCollector 46{ 47public: 48 IndexMeshVisitor(Optimizer* optimizer = 0) 49 : GeometryCollector(optimizer, Optimizer::INDEX_MESH), _generateNewIndicesOnAllGeometries(false) 50 { 51 } 52 inline void setGenerateNewIndicesOnAllGeometries(bool b) { _generateNewIndicesOnAllGeometries = b; } 53 inline bool getGenerateNewIndicesOnAllGeometries() const { return _generateNewIndicesOnAllGeometries; } 54 55 void makeMesh(osg::Geometry& geom); 56 void makeMesh(); 57protected: 58 bool _generateNewIndicesOnAllGeometries; 59}; 60 61// Optimize the triangle order in a mesh for best use of the GPU's 62// post-transform cache. This uses Tom Forsyth's algorithm described 63// at http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html 64class OSGUTIL_EXPORT VertexCacheVisitor : public GeometryCollector 65{ 66public: 67 VertexCacheVisitor(Optimizer* optimizer = 0) 68 : GeometryCollector(optimizer, Optimizer::VERTEX_POSTTRANSFORM) 69 { 70 } 71 72 void optimizeVertices(osg::Geometry& geom); 73 void optimizeVertices(); 74private: 75 void doVertexOptimization(osg::Geometry& geom, 76 std::vector<unsigned>& vertDrawList); 77}; 78 79// Gather statistics on post-transform cache misses for geometry 80class OSGUTIL_EXPORT VertexCacheMissVisitor : public osg::NodeVisitor 81{ 82public: 83 VertexCacheMissVisitor(unsigned cacheSize = 16); 84 void reset(); 85 virtual void apply(osg::Geometry& geom); 86 void doGeometry(osg::Geometry& geom); 87 unsigned misses; 88 unsigned triangles; 89protected: 90 const unsigned _cacheSize; 91}; 92 93// Optimize the use of the GPU pre-transform cache by arranging vertex 94// attributes in the order they are used. 95class OSGUTIL_EXPORT VertexAccessOrderVisitor : public GeometryCollector 96{ 97 struct OrderByPrimitiveMode 98 { 99 inline bool operator() (const osg::ref_ptr<osg::PrimitiveSet>& prim1, const osg::ref_ptr<osg::PrimitiveSet>& prim2) 100 { 101 if(prim1 && prim2) { 102 return prim1->getMode() > prim2->getMode(); 103 } 104 else if(prim1) { 105 return true; 106 } 107 return false; 108 } 109 } order_by_primitive_mode; 110 111public: 112 VertexAccessOrderVisitor(Optimizer* optimizer = 0) 113 : GeometryCollector(optimizer, Optimizer::VERTEX_PRETRANSFORM) 114 { 115 } 116 void optimizeOrder(); 117 void optimizeOrder(osg::Geometry& geom); 118}; 119 120class OSGUTIL_EXPORT SharedArrayOptimizer 121{ 122public: 123 void findDuplicatedUVs(const osg::Geometry& geometry); 124 void deduplicateUVs(osg::Geometry& geometry); 125protected: 126 std::map<unsigned int, unsigned int> _deduplicateUvs; 127}; // SharedArrayOptimizer 128 129 130inline void optimizeMesh(osg::Node* node) 131{ 132 IndexMeshVisitor imv; 133 node->accept(imv); 134 imv.makeMesh(); 135 136 VertexCacheVisitor vcv; 137 node->accept(vcv); 138 vcv.optimizeVertices(); 139 140 VertexAccessOrderVisitor vaov; 141 node->accept(vaov); 142 vaov.optimizeOrder(); 143} 144 145} 146#endif 147