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;