/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #ifndef OSGUTIL_MESHOPTIMIZERS #define OSGUTIL_MESHOPTIMIZERS 1 #include #include #include #include #include #include namespace osgUtil { // Helper that collects all the unique Geometry objects in a subgraph. class OSGUTIL_EXPORT GeometryCollector : public BaseOptimizerVisitor { public: GeometryCollector(Optimizer* optimizer, Optimizer::OptimizationOptions options) : BaseOptimizerVisitor(optimizer, options) {} void reset(); void apply(osg::Geometry& geom); typedef std::set GeometryList; GeometryList& getGeometryList() { return _geometryList; }; protected: GeometryList _geometryList; }; // Convert geometry that uses DrawArrays to DrawElements i.e., // construct a real mesh. This removes duplicate vertices. class OSGUTIL_EXPORT IndexMeshVisitor : public GeometryCollector { public: IndexMeshVisitor(Optimizer* optimizer = 0) : GeometryCollector(optimizer, Optimizer::INDEX_MESH), _isForcedReindexationEnable(false) { } inline void setGenerateNewIndicesOnAllGeometries(bool b) { _generateNewIndicesOnAllGeometries = b; } inline bool getGenerateNewIndicesOnAllGeometries() const { return _generateNewIndicesOnAllGeometries; } void makeMesh(osg::Geometry& geom); void makeMesh(); protected: bool _generateNewIndicesOnAllGeometries; }; // Optimize the triangle order in a mesh for best use of the GPU's // post-transform cache. This uses Tom Forsyth's algorithm described // at http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html class OSGUTIL_EXPORT VertexCacheVisitor : public GeometryCollector { public: VertexCacheVisitor(Optimizer* optimizer = 0) : GeometryCollector(optimizer, Optimizer::VERTEX_POSTTRANSFORM) { } void optimizeVertices(osg::Geometry& geom); void optimizeVertices(); private: void doVertexOptimization(osg::Geometry& geom, std::vector& vertDrawList); }; // Gather statistics on post-transform cache misses for geometry class OSGUTIL_EXPORT VertexCacheMissVisitor : public osg::NodeVisitor { public: VertexCacheMissVisitor(unsigned cacheSize = 16); void reset(); virtual void apply(osg::Geometry& geom); void doGeometry(osg::Geometry& geom); unsigned misses; unsigned triangles; protected: const unsigned _cacheSize; }; // Optimize the use of the GPU pre-transform cache by arranging vertex // attributes in the order they are used. class OSGUTIL_EXPORT VertexAccessOrderVisitor : public GeometryCollector { struct OrderByPrimitiveMode { inline bool operator() (const osg::ref_ptr& prim1, const osg::ref_ptr& prim2) { if(prim1 && prim2) { return prim1->getMode() > prim2->getMode(); } else if(prim1) { return true; } return false; } } order_by_primitive_mode; public: VertexAccessOrderVisitor(Optimizer* optimizer = 0) : GeometryCollector(optimizer, Optimizer::VERTEX_PRETRANSFORM) { } void optimizeOrder(); void optimizeOrder(osg::Geometry& geom); }; class OSGUTIL_EXPORT SharedArrayOptimizer { public: void findDuplicatedUVs(const osg::Geometry& geometry); void deduplicateUVs(osg::Geometry& geometry); protected: std::map _deduplicateUvs; }; // SharedArrayOptimizer inline void optimizeMesh(osg::Node* node) { IndexMeshVisitor imv; node->accept(imv); imv.makeMesh(); VertexCacheVisitor vcv; node->accept(vcv); vcv.optimizeVertices(); VertexAccessOrderVisitor vaov; node->accept(vaov); vaov.optimizeOrder(); } } #endif