From d52f4ea23a718271fcf22995298dbdf3978d4e15 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 18 Mar 2005 02:44:08 +0000 Subject: [PATCH] Added support for a new IsOperationPermissibleForObjectCallback in osgUtil::Optimizer. --- include/osgUtil/Optimizer | 289 +++++++++++++++++++------------- include/osgUtil/TriStripVisitor | 11 +- src/osgUtil/Optimizer.cpp | 76 ++++----- 3 files changed, 209 insertions(+), 167 deletions(-) diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index 766563ec1..678d19fce 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -81,6 +81,41 @@ class OSGUTIL_EXPORT Optimizer virtual void optimize(osg::Node* node, unsigned int options); + /** Callback for customizing what operations are permitted on objects in the scene graph.*/ + struct IsOperationPermissibleForObjectCallback : public osg::Referenced + { + virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::StateSet* stateset,unsigned int option) const + { + return optimizer->isOperationPermissibleForObjectImplementation(stateset,option); + } + + virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::StateAttribute* attribute,unsigned int option) const + { + return optimizer->isOperationPermissibleForObjectImplementation(attribute,option); + } + + virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::Drawable* drawable,unsigned int option) const + { + return optimizer->isOperationPermissibleForObjectImplementation(drawable,option); + } + + virtual bool isOperationPermissibleForObjectImplementation(const Optimizer* optimizer, const osg::Node* node,unsigned int option) const + { + return optimizer->isOperationPermissibleForObjectImplementation(node,option); + } + + }; + + /** Set the callback for customizing what operations are permitted on objects in the scene graph.*/ + void setIsOperationPermissibleForObjectCallback(IsOperationPermissibleForObjectCallback* callback) { _isOperationPermissibleForObjectCallback=callback; } + + /** Get the callback for customizing what operations are permitted on objects in the scene graph.*/ + IsOperationPermissibleForObjectCallback* getIsOperationPermissibleForObjectCallback() { return _isOperationPermissibleForObjectCallback.get(); } + + /** Get the callback for customizing what operations are permitted on objects in the scene graph.*/ + const IsOperationPermissibleForObjectCallback* getIsOperationPermissibleForObjectCallback() const { return _isOperationPermissibleForObjectCallback.get(); } + + inline void setPermissibleOptimizationsForObject(const osg::Object* object, unsigned int options) { _permissibleOptimizationsMap[object] = options; @@ -92,38 +127,133 @@ class OSGUTIL_EXPORT Optimizer if (itr!=_permissibleOptimizationsMap.end()) return itr->second; else return 0xffffffff; } - - inline bool isOperationPermissibleForObject(const osg::Object* object,unsigned int option) const + + + inline bool isOperationPermissibleForObject(const osg::StateSet* object, unsigned int option) const { - return (option & getPermissibleOptimizationsForObject(object))!=0; + if (_isOperationPermissibleForObjectCallback.valid()) + _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option); + else + return isOperationPermissibleForObjectImplementation(object,option); + } + + inline bool isOperationPermissibleForObject(const osg::StateAttribute* object, unsigned int option) const + { + if (_isOperationPermissibleForObjectCallback.valid()) + _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option); + else + return isOperationPermissibleForObjectImplementation(object,option); + } + + inline bool isOperationPermissibleForObject(const osg::Drawable* object, unsigned int option) const + { + if (_isOperationPermissibleForObjectCallback.valid()) + _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option); + else + return isOperationPermissibleForObjectImplementation(object,option); + } + + inline bool isOperationPermissibleForObject(const osg::Node* object, unsigned int option) const + { + if (_isOperationPermissibleForObjectCallback.valid()) + _isOperationPermissibleForObjectCallback->isOperationPermissibleForObjectImplementation(this,object,option); + else + return isOperationPermissibleForObjectImplementation(object,option); + } + + bool isOperationPermissibleForObjectImplementation(const osg::StateSet* stateset, unsigned int option) const + { + return (option & getPermissibleOptimizationsForObject(stateset))!=0; } - typedef std::map PermissibleOptimizationsMap; + bool isOperationPermissibleForObjectImplementation(const osg::StateAttribute* attribute, unsigned int option) const + { + return (option & getPermissibleOptimizationsForObject(attribute))!=0; + } - PermissibleOptimizationsMap& getPermissibleOptionsMap() { return _permissibleOptimizationsMap; } - const PermissibleOptimizationsMap& getPermissibleOptionsMap() const { return _permissibleOptimizationsMap; } - + bool isOperationPermissibleForObjectImplementation(const osg::Drawable* drawable, unsigned int option) const + { + if (option & (REMOVE_REDUNDANT_NODES|MERGE_GEOMETRY)) + { + if (drawable->getUserData()) return false; + if (drawable->getUpdateCallback()) return false; + if (drawable->getEventCallback()) return false; + if (drawable->getCullCallback()) return false; + } + return (option & getPermissibleOptimizationsForObject(drawable))!=0; + } + + bool isOperationPermissibleForObjectImplementation(const osg::Node* node, unsigned int option) const + { + if (option & (REMOVE_REDUNDANT_NODES|COMBINE_ADJACENT_LODS|FLATTEN_STATIC_TRANSFORMS)) + { + if (node->getUserData()) return false; + if (node->getUpdateCallback()) return false; + if (node->getEventCallback()) return false; + if (node->getCullCallback()) return false; + if (node->getNumDescriptions()>0) return false; + if (node->getStateSet()) return false; + if (node->getNodeMask()!=0xffffffff) return false; + if (!node->getName().empty()) return false; + } + + return (option & getPermissibleOptimizationsForObject(node))!=0; + } protected: + + osg::ref_ptr _isOperationPermissibleForObjectCallback; + + typedef std::map PermissibleOptimizationsMap; + PermissibleOptimizationsMap _permissibleOptimizationsMap; - PermissibleOptimizationsMap _permissibleOptimizationsMap; - - public: + class OSGUTIL_EXPORT BaseOptimizerVisitor : public osg::NodeVisitor + { + public: + + BaseOptimizerVisitor(Optimizer* optimizer, unsigned int operation): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _optimizer(optimizer), + _operationType(operation) {} + + inline bool isOperationPermissibleForObject(const osg::StateSet* object) const + { + return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) : true; + } + + inline bool isOperationPermissibleForObject(const osg::StateAttribute* object) const + { + return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) : true; + } + + inline bool isOperationPermissibleForObject(const osg::Drawable* object) const + { + return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) : true; + } + + inline bool isOperationPermissibleForObject(const osg::Node* object) const + { + return _optimizer ? _optimizer->isOperationPermissibleForObject(object,_operationType) : true; + } + + protected: + + Optimizer* _optimizer; + unsigned int _operationType; + }; + /** Flatten Static Transform nodes by applying their transform to the * geometry on the leaves of the scene graph, then removing the * now redundant transforms.*/ - class OSGUTIL_EXPORT FlattenStaticTransformsVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT FlattenStaticTransformsVisitor : public BaseOptimizerVisitor { public: - - FlattenStaticTransformsVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {} virtual void apply(osg::Node& geode); virtual void apply(osg::Geode& geode); @@ -132,12 +262,6 @@ class OSGUTIL_EXPORT Optimizer bool removeTransforms(osg::Node* nodeWeCannotRemove); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,FLATTEN_STATIC_TRANSFORMS) : true; - } - - protected: typedef std::vector TransformStack; @@ -146,7 +270,6 @@ class OSGUTIL_EXPORT Optimizer typedef std::set NodeSet; typedef std::set TransformSet; - Optimizer* _optimizer; TransformStack _transformStack; NodeSet _excludedNodeSet; DrawableSet _drawableSet; @@ -156,32 +279,25 @@ class OSGUTIL_EXPORT Optimizer /** Combine Static Transform nodes that sit above one another.*/ - class OSGUTIL_EXPORT CombineStaticTransformsVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT CombineStaticTransformsVisitor : public BaseOptimizerVisitor { public: CombineStaticTransformsVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, FLATTEN_STATIC_TRANSFORMS) {} virtual void apply(osg::MatrixTransform& transform); bool removeTransforms(osg::Node* nodeWeCannotRemove); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,FLATTEN_STATIC_TRANSFORMS) : true; - } - protected: typedef std::set TransformSet; - Optimizer* _optimizer; TransformSet _transformSet; }; /** Remove rendundant nodes, such as groups with one single child.*/ - class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public BaseOptimizerVisitor { public: @@ -190,24 +306,17 @@ class OSGUTIL_EXPORT Optimizer NodeList _redundantNodeList; RemoveEmptyNodesVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {} virtual void apply(osg::Geode& geode); virtual void apply(osg::Group& group); void removeEmptyNodes(); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,REMOVE_REDUNDANT_NODES) : true; - } - - Optimizer* _optimizer; }; /** Remove rendundant nodes, such as groups with one single child.*/ - class OSGUTIL_EXPORT RemoveRedundantNodesVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT RemoveRedundantNodesVisitor : public BaseOptimizerVisitor { public: @@ -215,31 +324,25 @@ class OSGUTIL_EXPORT Optimizer NodeList _redundantNodeList; RemoveRedundantNodesVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {} virtual void apply(osg::Group& group); virtual void apply(osg::Transform& transform); void removeRedundantNodes(); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,REMOVE_REDUNDANT_NODES) : true; - } - - Optimizer* _optimizer; }; /** Tesselate all geodes, to remove POLYGONS.*/ - class OSGUTIL_EXPORT TesselateVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT TesselateVisitor : public BaseOptimizerVisitor { public: typedef std::set GroupList; GroupList _groupList; - TesselateVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + TesselateVisitor(Optimizer* optimizer=0): + BaseOptimizerVisitor(optimizer, TESSELATE_GEOMETRY) {} virtual void apply(osg::Geode& geode); @@ -247,7 +350,7 @@ class OSGUTIL_EXPORT Optimizer /** Optimize the LOD groups, by combining adjacent LOD's which have * complementary ranges.*/ - class OSGUTIL_EXPORT CombineLODsVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT CombineLODsVisitor : public BaseOptimizerVisitor { public: @@ -255,32 +358,24 @@ class OSGUTIL_EXPORT Optimizer GroupList _groupList; CombineLODsVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, COMBINE_ADJACENT_LODS) {} virtual void apply(osg::LOD& lod); void combineLODs(); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,COMBINE_ADJACENT_LODS) : true; - } - - Optimizer* _optimizer; }; /** 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 + class OSGUTIL_EXPORT StateVisitor : public BaseOptimizerVisitor { public: /// default to traversing all children. StateVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, SHARE_DUPLICATE_STATE) {} /** empty visitor, make it ready for next traversal.*/ virtual void reset(); @@ -291,11 +386,6 @@ class OSGUTIL_EXPORT Optimizer void optimize(); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,SHARE_DUPLICATE_STATE) : true; - } - protected: void addStateSet(osg::StateSet* stateset,osg::Object* obj); @@ -303,41 +393,31 @@ class OSGUTIL_EXPORT Optimizer typedef std::set ObjectSet; typedef std::map StateSetMap; - Optimizer* _optimizer; StateSetMap _statesets; }; - class OSGUTIL_EXPORT CheckGeometryVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT CheckGeometryVisitor : public BaseOptimizerVisitor { public: /// default to traversing all children. CheckGeometryVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, CHECK_GEOMETRY) {} virtual void apply(osg::Geode& geode) { checkGeode(geode); } void checkGeode(osg::Geode& geode); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,CHECK_GEOMETRY) : true; - } - - Optimizer* _optimizer; - }; - class OSGUTIL_EXPORT MergeGeometryVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT MergeGeometryVisitor : public BaseOptimizerVisitor { public: /// default to traversing all children. MergeGeometryVisitor(Optimizer* optimizer=0) : - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, MERGE_GEOMETRY) {} virtual void apply(osg::Geode& geode) { mergeGeode(geode); } virtual void apply(osg::Billboard&) { /* don't do anything*/ } @@ -354,22 +434,15 @@ class OSGUTIL_EXPORT Optimizer static bool mergePrimitive(osg::DrawElementsUShort& lhs,osg::DrawElementsUShort& rhs); static bool mergePrimitive(osg::DrawElementsUInt& lhs,osg::DrawElementsUInt& rhs); - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,MERGE_GEOMETRY) : true; - } - - Optimizer* _optimizer; }; /** Spatialize scene into a balanced quad/oct tree.*/ - class OSGUTIL_EXPORT SpatializeGroupsVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT SpatializeGroupsVisitor : public BaseOptimizerVisitor { public: SpatializeGroupsVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, SPATIALIZE_GROUPS) {} virtual void apply(osg::Group& group); @@ -380,23 +453,15 @@ class OSGUTIL_EXPORT Optimizer typedef std::set GroupsToDivideList; GroupsToDivideList _groupsToDivideList; - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,SPATIALIZE_GROUPS) : true; - } - - Optimizer* _optimizer; - }; /** Copy any shared subgraphs, enabling flattening of static transforms.*/ - class OSGUTIL_EXPORT CopySharedSubgraphsVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT CopySharedSubgraphsVisitor : public BaseOptimizerVisitor { public: CopySharedSubgraphsVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer) {} + BaseOptimizerVisitor(optimizer, COPY_SHARED_NODES) {} virtual void apply(osg::Node& node); @@ -405,18 +470,11 @@ class OSGUTIL_EXPORT Optimizer typedef std::set SharedNodeList; SharedNodeList _sharedNodeList; - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,COPY_SHARED_NODES) : true; - } - - Optimizer* _optimizer; - }; /** For all textures apply settings.*/ - class OSGUTIL_EXPORT TextureVisitor : public osg::NodeVisitor + class OSGUTIL_EXPORT TextureVisitor : public BaseOptimizerVisitor { public: @@ -424,8 +482,7 @@ class OSGUTIL_EXPORT Optimizer bool changeClientImageStorage, bool valueClientImageStorage, bool changeAnisotropy, float valueAnisotropy, Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _optimizer(optimizer), + BaseOptimizerVisitor(optimizer, OPTIMIZE_TEXTURE_SETTINGS), _changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef), _changeClientImageStorage(changeClientImageStorage), _valueClientImageStorage(valueClientImageStorage), _changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy) {} @@ -435,22 +492,14 @@ class OSGUTIL_EXPORT Optimizer void apply(osg::StateSet& stateset); void apply(osg::Texture& texture); - - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,OPTIMIZE_TEXTURE_SETTINGS) : true; - } - Optimizer* _optimizer; bool _changeAutoUnRef, _valueAutoUnRef; bool _changeClientImageStorage, _valueClientImageStorage; bool _changeAnisotropy; float _valueAnisotropy; - - }; - + }; } diff --git a/include/osgUtil/TriStripVisitor b/include/osgUtil/TriStripVisitor index 3a018eee9..e5ec820a3 100644 --- a/include/osgUtil/TriStripVisitor +++ b/include/osgUtil/TriStripVisitor @@ -27,13 +27,13 @@ namespace osgUtil { /** A tri stripping visitor for converting Geometry surface primitives into tri strips. * The current implemention is based upon Tanguy Fautre's triangulation code. */ -class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor +class OSGUTIL_EXPORT TriStripVisitor : public Optimizer::BaseOptimizerVisitor { public: /// default to traversing all children. - TriStripVisitor(Optimizer* =0) : - osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), + TriStripVisitor(Optimizer* optimizer=0) : + Optimizer::BaseOptimizerVisitor( optimizer, Optimizer::TRISTRIP_GEOMETRY), _cacheSize( 16 ), _minStripSize( 2 ), _generateFourPointPrimitivesQuads ( false) @@ -81,10 +81,6 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor return _minStripSize; } - inline bool isOperationPermissibleForObject(const osg::Object* object) const - { - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,osgUtil::Optimizer::TRISTRIP_GEOMETRY) : true; - } void setGenerateFourPointPrimitivesQuads(bool flag) { _generateFourPointPrimitivesQuads = flag; } bool getGenerateFourPointPrimitivesQuads() const { return _generateFourPointPrimitivesQuads; } @@ -94,7 +90,6 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor typedef std::set GeometryList; - Optimizer* _optimizer; unsigned int _cacheSize; unsigned int _minStripSize; GeometryList _geometryList; diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 8046f03ba..51eca9b8e 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -37,26 +38,9 @@ using namespace osgUtil; -//////////////////////////////////////////////////////////////////////////// -// Overall Optimization function. -//////////////////////////////////////////////////////////////////////////// - -static bool isNodeEmpty(const osg::Node& node) -{ - if (node.getUserData()) return false; - if (node.getUpdateCallback()) return false; - if (node.getEventCallback()) return false; - if (node.getCullCallback()) return false; - if (node.getNumDescriptions()>0) return false; - if (node.getStateSet()) return false; - if (node.getNodeMask()!=0xffffffff) return false; - if (!node.getName().empty()) return false; - return true; -} void Optimizer::reset() { - _permissibleOptimizationsMap.clear(); } static osg::ApplicationUsageProxy Optimizer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_OPTIMIZER \" []\"","OFF | DEFAULT | FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS"); @@ -501,15 +485,14 @@ void Optimizer::StateVisitor::optimize() // Flatten static transforms //////////////////////////////////////////////////////////////////////////// -class CollectLowestTransformsVisitor : public osg::NodeVisitor +class CollectLowestTransformsVisitor : public Optimizer::BaseOptimizerVisitor { public: CollectLowestTransformsVisitor(Optimizer* optimizer=0): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS), - _transformFunctor(osg::Matrix()), - _optimizer(optimizer) {} + Optimizer::BaseOptimizerVisitor(optimizer,Optimizer::FLATTEN_STATIC_TRANSFORMS), + _transformFunctor(osg::Matrix()) {} virtual void apply(osg::Node& node) { @@ -587,16 +570,29 @@ class CollectLowestTransformsVisitor : public osg::NodeVisitor void disableTransform(osg::Transform* transform); bool removeTransforms(osg::Node* nodeWeCannotRemove); - inline bool isOperationPermissibleForObject(const osg::Object* object) + inline bool isOperationPermissibleForObject(const osg::Object* object) const + { + const osg::Drawable* drawable = dynamic_cast(object); + if (drawable) return isOperationPermissibleForObject(drawable); + + const osg::Node* node = dynamic_cast(object); + if (drawable) return isOperationPermissibleForObject(node); + + return false; + } + + inline bool isOperationPermissibleForObject(const osg::Drawable* drawable) const { // disable if cannot apply transform functor. - const osg::Drawable* drawable = dynamic_cast(object); if (drawable && !drawable->supports(_transformFunctor)) return false; + return BaseOptimizerVisitor::isOperationPermissibleForObject(drawable); + } + inline bool isOperationPermissibleForObject(const osg::Node* node) const + { // disable if object is a light point node. - if (strcmp(object->className(),"LightPointNode")==0) return false; - - return _optimizer ? _optimizer->isOperationPermissibleForObject(object,Optimizer::FLATTEN_STATIC_TRANSFORMS) : true; + if (strcmp(node->className(),"LightPointNode")==0) return false; + return BaseOptimizerVisitor::isOperationPermissibleForObject(node); } protected: @@ -682,7 +678,6 @@ class CollectLowestTransformsVisitor : public osg::NodeVisitor void doTransform(osg::Object* obj,osg::Matrix& matrix); osgUtil::TransformAttributeFunctor _transformFunctor; - Optimizer* _optimizer; TransformMap _transformMap; ObjectMap _objectMap; ObjectList _currentObjectList; @@ -1004,7 +999,7 @@ bool Optimizer::FlattenStaticTransformsVisitor::removeTransforms(osg::Node* node } //////////////////////////////////////////////////////////////////////////// -// RemoveEmptyNodes. +// CombineStatucTransforms //////////////////////////////////////////////////////////////////////////// void Optimizer::CombineStaticTransformsVisitor::apply(osg::MatrixTransform& transform) @@ -1013,7 +1008,8 @@ void Optimizer::CombineStaticTransformsVisitor::apply(osg::MatrixTransform& tran transform.getNumChildren()==1 && transform.getChild(0)->asTransform()!=0 && transform.getChild(0)->asTransform()->asMatrixTransform()!=0 && - transform.getChild(0)->asTransform()->getDataVariance()==osg::Object::STATIC) + transform.getChild(0)->asTransform()->getDataVariance()==osg::Object::STATIC && + isOperationPermissibleForObject(&transform) && isOperationPermissibleForObject(transform.getChild(0))) { _transformSet.insert(&transform); } @@ -1076,16 +1072,15 @@ void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Geode& geode) for(int i=geode.getNumDrawables()-1;i>=0;--i) { osg::Geometry* geom = geode.getDrawable(i)->asGeometry(); - if (geom && geom->empty()) + if (geom && geom->empty() && isOperationPermissibleForObject(geom)) { geode.removeDrawable(i); } } - if (geode.getNumParents()>0) { - if (geode.getNumDrawables()==0 && isNodeEmpty(geode)) _redundantNodeList.insert(&geode); + if (geode.getNumDrawables()==0 && isOperationPermissibleForObject(&geode)) _redundantNodeList.insert(&geode); } } @@ -1094,7 +1089,7 @@ void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group) if (group.getNumParents()>0) { // only remove empty groups, but not empty occluders. - if (group.getNumChildren()==0 && isNodeEmpty(group) && + if (group.getNumChildren()==0 && isOperationPermissibleForObject(&group) && (typeid(group)==typeid(osg::Group) || dynamic_cast(&group))) { _redundantNodeList.insert(&group); @@ -1154,7 +1149,7 @@ void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Group& group) { if (group.getNumParents()>0 && group.getNumChildren()<=1) { - if (isNodeEmpty(group) && isOperationPermissibleForObject(&group)) + if (isOperationPermissibleForObject(&group)) { _redundantNodeList.insert(&group); } @@ -1223,13 +1218,16 @@ void Optimizer::RemoveRedundantNodesVisitor::removeRedundantNodes() //////////////////////////////////////////////////////////////////////////// void Optimizer::CombineLODsVisitor::apply(osg::LOD& lod) { - for(unsigned int i=0;i(&lod)!=0) + { + for(unsigned int i=0;i