Added support for a new IsOperationPermissibleForObjectCallback in osgUtil::Optimizer.
This commit is contained in:
parent
f8426a8ad8
commit
d52f4ea23a
@ -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;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user