Added support for a new IsOperationPermissibleForObjectCallback in osgUtil::Optimizer.

This commit is contained in:
Robert Osfield 2005-03-18 02:44:08 +00:00
parent f8426a8ad8
commit d52f4ea23a
3 changed files with 209 additions and 167 deletions

View File

@ -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<const osg::Object*,unsigned int> 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> _isOperationPermissibleForObjectCallback;
typedef std::map<const osg::Object*,unsigned int> 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<osg::Transform*> TransformStack;
@ -146,7 +270,6 @@ class OSGUTIL_EXPORT Optimizer
typedef std::set<osg::Node* > NodeSet;
typedef std::set<osg::Transform*> 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<osg::MatrixTransform*> 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<osg::Group*> 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<osg::Object*> ObjectSet;
typedef std::map<osg::StateSet*,ObjectSet> 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<osg::Group*> 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<osg::Node*> 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;
};
};
}

View File

@ -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<osg::Geometry*> GeometryList;
Optimizer* _optimizer;
unsigned int _cacheSize;
unsigned int _minStripSize;
GeometryList _geometryList;

View File

@ -25,6 +25,7 @@
#include <osg/Sequence>
#include <osg/Switch>
#include <osg/Texture>
#include <osg/PagedLOD>
#include <osgUtil/TransformAttributeFunctor>
#include <osgUtil/TriStripVisitor>
@ -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 \"<type> [<type>]\"","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<const osg::Drawable*>(object);
if (drawable) return isOperationPermissibleForObject(drawable);
const osg::Node* node = dynamic_cast<const osg::Node*>(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<const osg::Drawable*>(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<osg::Transform*>(&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.getNumParents();++i)
{
if (typeid(*lod.getParent(i))==typeid(osg::Group))
if (dynamic_cast<osg::PagedLOD*>(&lod)!=0)
{
for(unsigned int i=0;i<lod.getNumParents();++i)
{
if (isOperationPermissibleForObject(&lod))
if (typeid(*lod.getParent(i))==typeid(osg::Group))
{
_groupList.insert(lod.getParent(i));
if (isOperationPermissibleForObject(&lod))
{
_groupList.insert(lod.getParent(i));
}
}
}
}