//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield //Distributed under the terms of the GNU Library General Public License (LGPL) //as published by the Free Software Foundation. #ifndef OSGUTIL_OPTIMIZER #define OSGUTIL_OPTIMIZER #include #include #include #include #include namespace osgUtil { /** Insert impostor nodes into scene graph. * For example of usage see src/Demos/osgimpostor. */ class OSGUTIL_EXPORT Optimizer { public: Optimizer() {} enum OptimizationOptions { FLATTEN_STATIC_TRANSFORMS = 0x1, REMOVE_REDUNDENT_NODES = 0x2, COMBINE_ADJACENT_LODS = 0x4, SHARE_DUPLICATE_STATE = 0x8, ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDENT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE }; /** traverse the node and its subgraph with a series of optimization * visitors, specificied by the OptizationOptions.*/ virtual void optimize(osg::Node* node, unsigned int options = ALL_OPTIMIZATIONS); /** ConvertGeoSetsToGeometryVisitor all the old GeoSet Drawables to the new Geometry Drawables.*/ class OSGUTIL_EXPORT ConvertGeoSetsToGeometryVisitor : public osg::NodeVisitor { public: ConvertGeoSetsToGeometryVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} virtual void apply(osg::Geode& geode); virtual void apply(osg::Node& node) { traverse(node); } }; /** Flatten Static Trasform nodes by applying their transform to the * geometry on the leaves of the scene graph, then removing the * now redundent transforms.*/ class OSGUTIL_EXPORT FlattenStaticTransformsVisitor : public osg::NodeVisitor { public: FlattenStaticTransformsVisitor(bool ignoreDynamicTransforms=true): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _ignoreDynamicTransforms(ignoreDynamicTransforms) {} virtual void apply(osg::Geode& geode); virtual void apply(osg::Billboard& billboard); virtual void apply(osg::LOD& lod); virtual void apply(osg::Transform& transform); void removeTransforms(); typedef std::vector TransformStack; typedef std::vector MatrixStack; protected: struct TransformStruct { typedef std::set ObjectSet; TransformStruct():_canBeApplied(true) {} void add(osg::Object* obj) { _objectSet.insert(obj); } bool _canBeApplied; ObjectSet _objectSet; }; struct ObjectStruct { typedef std::set TransformSet; ObjectStruct():_canBeApplied(true),_matrixSet(false),_moreThanOneMatrixRequired(false) {} void add(TransformStack& transforms,osg::Matrix& matrix) { _transformSet.insert(transforms.begin(),transforms.end()); if (!_matrixSet) { _matrixSet = true; _moreThanOneMatrixRequired = false; _matrix = matrix; } else if (_matrix!=matrix) { _moreThanOneMatrixRequired = true; } } bool _canBeApplied; bool _matrixSet; bool _moreThanOneMatrixRequired; osg::Matrix _matrix; TransformSet _transformSet; }; typedef std::map TransformMap; typedef std::map ObjectMap; void disableObject(osg::Object* object) { disableObject(_objectMap.find(object)); } void disableObject(ObjectMap::iterator itr); void disableTransform(osg::Transform* transform); void doTransform(osg::Object* obj,osg::Matrix& matrix); bool _ignoreDynamicTransforms; MatrixStack _matrixStack; TransformStack _transformStack; TransformMap _transformMap; ObjectMap _objectMap; }; /** Remove the lowest static transforms in the scene.*/ class OSGUTIL_EXPORT RemoveLowestStaticTransformsVisitor : public osg::NodeVisitor { public: RemoveLowestStaticTransformsVisitor(bool ignoreDynamicTransforms=true): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _ignoreDynamicTransforms(ignoreDynamicTransforms) {} virtual void apply(osg::Geode& geode); virtual void apply(osg::Billboard& billboard); virtual void apply(osg::LOD& lod); virtual void apply(osg::Transform& transform); bool removeTransforms(); typedef std::vector TransformStack; typedef std::vector MatrixStack; protected: struct TransformStruct { typedef std::set ObjectSet; TransformStruct():_containsTransform(false),_canBeApplied(true) {} void add(osg::Object* obj) { _objectSet.insert(obj); } bool _containsTransform; bool _canBeApplied; ObjectSet _objectSet; }; struct ObjectStruct { typedef std::set TransformSet; ObjectStruct():_canBeApplied(true),_matrixSet(false),_moreThanOneMatrixRequired(false) {} void add(osg::Transform* transform,osg::Matrix& matrix) { _transformSet.insert(transform); if (!_matrixSet) { _matrixSet = true; _moreThanOneMatrixRequired = false; _matrix = matrix; } else if (_matrix!=matrix) { _moreThanOneMatrixRequired = true; } } bool _canBeApplied; bool _matrixSet; bool _moreThanOneMatrixRequired; osg::Matrix _matrix; TransformSet _transformSet; }; typedef std::map TransformMap; typedef std::map ObjectMap; void disableObject(osg::Object* object) { disableObject(_objectMap.find(object)); } void disableObject(ObjectMap::iterator itr); void disableTransform(osg::Transform* transform); void doTransform(osg::Object* obj,osg::Matrix& matrix); bool _ignoreDynamicTransforms; MatrixStack _matrixStack; TransformStack _transformStack; TransformMap _transformMap; ObjectMap _objectMap; }; /** Remove rendundent nodes, such as groups with one single child.*/ class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public osg::NodeVisitor { public: typedef std::set NodeList; NodeList _redundentNodeList; RemoveEmptyNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} virtual void apply(osg::Geode& geode); virtual void apply(osg::Group& group); void removeEmptyNodes(); }; /** Remove rendundent nodes, such as groups with one single child.*/ class OSGUTIL_EXPORT RemoveRedundentNodesVisitor : public osg::NodeVisitor { public: typedef std::set NodeList; NodeList _redundentNodeList; RemoveRedundentNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} virtual void apply(osg::Group& group); virtual void apply(osg::Transform& transform); void removeRedundentNodes(); }; /** Optimize the LOD groups, by combining adjacent LOD's which have * complementary ranges.*/ class OSGUTIL_EXPORT CombineLODsVisitor : public osg::NodeVisitor { public: typedef std::set GroupList; GroupList _groupList; CombineLODsVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} virtual void apply(osg::LOD& lod); void combineLODs(); }; /** Optimize State in the scene graph by removing duplicate state, * replacing it with shared instances, both for StateAttributes, * and whole StateSets.*/ class OSGUTIL_EXPORT StateVisitor : public osg::NodeVisitor { public: /// default to traversing all children. StateVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {} /** empty visitor, make it ready for next traversal.*/ virtual void reset(); virtual void apply(osg::Node& node); virtual void apply(osg::Geode& geode); void optimize(); protected: void addStateSet(osg::StateSet* stateset,osg::Object* obj); typedef std::set ObjectSet; typedef std::map StateSetMap; StateSetMap _statesets; }; class OSGUTIL_EXPORT MergeGeometryVisitor : public osg::NodeVisitor { public: /// default to traversing all children. MergeGeometryVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {} virtual void apply(osg::Geode& geode) { mergeGeode(geode); } virtual void apply(osg::Billboard&) { /* don't do anything*/ } static bool mergeGeode(osg::Geode& geode); static bool mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs); }; }; } #endif