Added support for controlling what optimization operations can be applied
to specific nodes in the scene graph. Typical use would be tagging a node so that it can't be optimized away in say a flatten static transform pass. Added methods to Optimizer are: inline void setPermissableOptionsForObject(const osg::Object* object, unsigned int options) { _permissableOptionsMap[object] = options; } inline unsigned int getPermissableOptionsForObject(const osg::Object* object) const { PermissableOptionsMap::const_iterator itr = _permissableOptionsMap.find(object); if (itr!=_permissableOptionsMap.end()) return itr->second; else return 0xffffffff; } inline bool isOperationPermissableForObject(const osg::Object* object,unsigned int option) const { return (option & getPermissableOptionsForObject(object))!=0; }
This commit is contained in:
parent
5295d68fd3
commit
1881610a35
@ -35,6 +35,7 @@ class OSGUTIL_EXPORT Optimizer
|
||||
public:
|
||||
|
||||
Optimizer() {}
|
||||
virtual ~Optimizer() {}
|
||||
|
||||
enum OptimizationOptions
|
||||
{
|
||||
@ -64,6 +65,9 @@ class OSGUTIL_EXPORT Optimizer
|
||||
TRISTRIP_GEOMETRY
|
||||
};
|
||||
|
||||
/** reset internal data to initial state - the getPrimissableOptionsMap is cleared.*/
|
||||
void reset();
|
||||
|
||||
/** traverse the node and its subgraph with a series of optimization
|
||||
* visitors, specificied by the OptizationOptions.*/
|
||||
void optimize(osg::Node* node);
|
||||
@ -73,6 +77,35 @@ class OSGUTIL_EXPORT Optimizer
|
||||
virtual void optimize(osg::Node* node, unsigned int options);
|
||||
|
||||
|
||||
inline void setPermissableOptionsForObject(const osg::Object* object, unsigned int options)
|
||||
{
|
||||
_permissableOptionsMap[object] = options;
|
||||
}
|
||||
|
||||
inline unsigned int getPermissableOptionsForObject(const osg::Object* object) const
|
||||
{
|
||||
PermissableOptionsMap::const_iterator itr = _permissableOptionsMap.find(object);
|
||||
if (itr!=_permissableOptionsMap.end()) return itr->second;
|
||||
else return 0xffffffff;
|
||||
}
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object,unsigned int option) const
|
||||
{
|
||||
return (option & getPermissableOptionsForObject(object))!=0;
|
||||
}
|
||||
|
||||
typedef std::map<const osg::Object*,unsigned int> PermissableOptionsMap;
|
||||
|
||||
PermissableOptionsMap& getPrimissableOptionsMap() { return _permissableOptionsMap; }
|
||||
const PermissableOptionsMap& getPrimissableOptionsMap() const { return _permissableOptionsMap; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
PermissableOptionsMap _permissableOptionsMap;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/** Flatten Static Trasform nodes by applying their transform to the
|
||||
@ -84,8 +117,9 @@ class OSGUTIL_EXPORT Optimizer
|
||||
|
||||
|
||||
|
||||
FlattenStaticTransformsVisitor():
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
FlattenStaticTransformsVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Geode& geode);
|
||||
virtual void apply(osg::Billboard& geode);
|
||||
@ -93,6 +127,11 @@ class OSGUTIL_EXPORT Optimizer
|
||||
|
||||
bool removeTransforms(osg::Node* nodeWeCannotRemove);
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,FLATTEN_STATIC_TRANSFORMS) : true;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@ -100,7 +139,8 @@ class OSGUTIL_EXPORT Optimizer
|
||||
typedef std::set<osg::Drawable*> DrawableSet;
|
||||
typedef std::set<osg::Billboard*> BillboardSet;
|
||||
typedef std::set<osg::Transform*> TransformSet;
|
||||
|
||||
|
||||
Optimizer* _optimizer;
|
||||
TransformStack _transformStack;
|
||||
DrawableSet _drawableSet;
|
||||
BillboardSet _billboardSet;
|
||||
@ -113,16 +153,23 @@ class OSGUTIL_EXPORT Optimizer
|
||||
{
|
||||
public:
|
||||
|
||||
CombineStaticTransformsVisitor():
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
CombineStaticTransformsVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::MatrixTransform& transform);
|
||||
|
||||
bool removeTransforms(osg::Node* nodeWeCannotRemove);
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,FLATTEN_STATIC_TRANSFORMS) : true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::set<osg::MatrixTransform*> TransformSet;
|
||||
Optimizer* _optimizer;
|
||||
TransformSet _transformSet;
|
||||
};
|
||||
|
||||
@ -135,13 +182,21 @@ class OSGUTIL_EXPORT Optimizer
|
||||
typedef std::set<osg::Node*> NodeList;
|
||||
NodeList _redundantNodeList;
|
||||
|
||||
RemoveEmptyNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
|
||||
RemoveEmptyNodesVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Geode& geode);
|
||||
virtual void apply(osg::Group& group);
|
||||
|
||||
void removeEmptyNodes();
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,REMOVE_REDUNDANT_NODES) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
};
|
||||
|
||||
/** Remove rendundant nodes, such as groups with one single child.*/
|
||||
@ -152,13 +207,21 @@ class OSGUTIL_EXPORT Optimizer
|
||||
typedef std::set<osg::Node*> NodeList;
|
||||
NodeList _redundantNodeList;
|
||||
|
||||
RemoveRedundantNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
RemoveRedundantNodesVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Group& group);
|
||||
virtual void apply(osg::Transform& transform);
|
||||
|
||||
void removeRedundantNodes();
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,REMOVE_REDUNDANT_NODES) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
};
|
||||
|
||||
/** Optimize the LOD groups, by combining adjacent LOD's which have
|
||||
@ -170,12 +233,20 @@ class OSGUTIL_EXPORT Optimizer
|
||||
typedef std::set<osg::Group*> GroupList;
|
||||
GroupList _groupList;
|
||||
|
||||
CombineLODsVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
CombineLODsVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::LOD& lod);
|
||||
|
||||
void combineLODs();
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,COMBINE_ADJACENT_LODS) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
};
|
||||
|
||||
/** Optimize State in the scene graph by removing duplicate state,
|
||||
@ -186,7 +257,9 @@ class OSGUTIL_EXPORT Optimizer
|
||||
public:
|
||||
|
||||
/// default to traversing all children.
|
||||
StateVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}
|
||||
StateVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
/** empty visitor, make it ready for next traversal.*/
|
||||
virtual void reset();
|
||||
@ -197,6 +270,11 @@ class OSGUTIL_EXPORT Optimizer
|
||||
|
||||
void optimize();
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,SHARE_DUPLICATE_STATE) : true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void addStateSet(osg::StateSet* stateset,osg::Object* obj);
|
||||
@ -204,6 +282,7 @@ class OSGUTIL_EXPORT Optimizer
|
||||
typedef std::set<osg::Object*> ObjectSet;
|
||||
typedef std::map<osg::StateSet*,ObjectSet> StateSetMap;
|
||||
|
||||
Optimizer* _optimizer;
|
||||
StateSetMap _statesets;
|
||||
|
||||
};
|
||||
@ -213,11 +292,20 @@ class OSGUTIL_EXPORT Optimizer
|
||||
public:
|
||||
|
||||
/// default to traversing all children.
|
||||
CheckGeometryVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}
|
||||
CheckGeometryVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Geode& geode) { checkGeode(geode); }
|
||||
|
||||
static void checkGeode(osg::Geode& geode);
|
||||
void checkGeode(osg::Geode& geode);
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,CHECK_GEOMETRY) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
|
||||
};
|
||||
|
||||
@ -226,12 +314,14 @@ class OSGUTIL_EXPORT Optimizer
|
||||
public:
|
||||
|
||||
/// default to traversing all children.
|
||||
MergeGeometryVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {}
|
||||
MergeGeometryVisitor(Optimizer* optimizer=0) :
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Geode& geode) { mergeGeode(geode); }
|
||||
virtual void apply(osg::Billboard&) { /* don't do anything*/ }
|
||||
|
||||
static bool mergeGeode(osg::Geode& geode);
|
||||
bool mergeGeode(osg::Geode& geode);
|
||||
|
||||
static bool geometryContainsSharedArrays(osg::Geometry& geom);
|
||||
|
||||
@ -243,6 +333,12 @@ class OSGUTIL_EXPORT Optimizer
|
||||
static bool mergePrimitive(osg::DrawElementsUShort& lhs,osg::DrawElementsUShort& rhs);
|
||||
static bool mergePrimitive(osg::DrawElementsUInt& lhs,osg::DrawElementsUInt& rhs);
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,MERGE_GEOMETRY) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
};
|
||||
|
||||
/** Spatialize scene into a balanced quad/oct tree.*/
|
||||
@ -250,7 +346,9 @@ class OSGUTIL_EXPORT Optimizer
|
||||
{
|
||||
public:
|
||||
|
||||
SpatializeGroupsVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
SpatializeGroupsVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Group& group);
|
||||
|
||||
@ -261,6 +359,13 @@ class OSGUTIL_EXPORT Optimizer
|
||||
typedef std::set<osg::Group*> GroupsToDivideList;
|
||||
GroupsToDivideList _groupsToDivideList;
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,SPATIALIZE_GROUPS) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
|
||||
};
|
||||
|
||||
/** Copy any shared subgraphs, enabling flattening of static transforms.*/
|
||||
@ -268,7 +373,9 @@ class OSGUTIL_EXPORT Optimizer
|
||||
{
|
||||
public:
|
||||
|
||||
CopySharedSubgraphsVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
||||
CopySharedSubgraphsVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Node& node);
|
||||
|
||||
@ -276,6 +383,13 @@ class OSGUTIL_EXPORT Optimizer
|
||||
|
||||
typedef std::set<osg::Node*> SharedNodeList;
|
||||
SharedNodeList _sharedNodeList;
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,COPY_SHARED_NODES) : true;
|
||||
}
|
||||
|
||||
Optimizer* _optimizer;
|
||||
|
||||
};
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
|
||||
#include <osgUtil/Export>
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include <set>
|
||||
|
||||
@ -32,7 +32,7 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor
|
||||
public:
|
||||
|
||||
/// default to traversing all children.
|
||||
TriStripVisitor() :
|
||||
TriStripVisitor(Optimizer* optimizer=0) :
|
||||
osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
|
||||
_cacheSize( 16 ),
|
||||
_minStripSize( 2 )
|
||||
@ -80,10 +80,16 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor
|
||||
return _minStripSize;
|
||||
}
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,osgUtil::Optimizer::TRISTRIP_GEOMETRY) : true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
typedef std::set<osg::Geometry*> GeometryList;
|
||||
|
||||
Optimizer* _optimizer;
|
||||
unsigned int _cacheSize;
|
||||
unsigned int _minStripSize;
|
||||
GeometryList _geometryList;
|
||||
|
@ -50,6 +50,11 @@ static bool isNodeEmpty(const osg::Node& node)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Optimizer::reset()
|
||||
{
|
||||
_permissableOptionsMap.clear();
|
||||
}
|
||||
|
||||
static osg::ApplicationUsageProxy Optimizer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_OPTIMIZER \"<type> [<type>]\"","DEFAULT | FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY");
|
||||
|
||||
void Optimizer::optimize(osg::Node* node)
|
||||
@ -105,7 +110,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing COMBINE_ADJACENT_LODS"<<std::endl;
|
||||
|
||||
CombineLODsVisitor clv;
|
||||
CombineLODsVisitor clv(this);
|
||||
node->accept(clv);
|
||||
clv.combineLODs();
|
||||
}
|
||||
@ -114,7 +119,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SHARE_DUPLICATE_STATE"<<std::endl;
|
||||
|
||||
StateVisitor osv;
|
||||
StateVisitor osv(this);
|
||||
node->accept(osv);
|
||||
osv.optimize();
|
||||
}
|
||||
@ -123,7 +128,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing COPY_SHARED_NODES"<<std::endl;
|
||||
|
||||
CopySharedSubgraphsVisitor cssv;
|
||||
CopySharedSubgraphsVisitor cssv(this);
|
||||
node->accept(cssv);
|
||||
cssv.copySharedNodes();
|
||||
}
|
||||
@ -137,14 +142,14 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
do
|
||||
{
|
||||
osg::notify(osg::DEBUG_INFO) << "** RemoveStaticTransformsVisitor *** Pass "<<i<<std::endl;
|
||||
FlattenStaticTransformsVisitor fstv;
|
||||
FlattenStaticTransformsVisitor fstv(this);
|
||||
node->accept(fstv);
|
||||
result = fstv.removeTransforms(node);
|
||||
++i;
|
||||
} while (result);
|
||||
|
||||
// no combine any adjacent static transforms.
|
||||
CombineStaticTransformsVisitor cstv;
|
||||
CombineStaticTransformsVisitor cstv(this);
|
||||
node->accept(cstv);
|
||||
cstv.removeTransforms(node);
|
||||
|
||||
@ -155,11 +160,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing REMOVE_REDUNDANT_NODES"<<std::endl;
|
||||
|
||||
RemoveEmptyNodesVisitor renv;
|
||||
RemoveEmptyNodesVisitor renv(this);
|
||||
node->accept(renv);
|
||||
renv.removeEmptyNodes();
|
||||
|
||||
RemoveRedundantNodesVisitor rrnv;
|
||||
RemoveRedundantNodesVisitor rrnv(this);
|
||||
node->accept(rrnv);
|
||||
rrnv.removeRedundantNodes();
|
||||
|
||||
@ -169,7 +174,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SPATIALIZE_GROUPS"<<std::endl;
|
||||
|
||||
SpatializeGroupsVisitor sv;
|
||||
SpatializeGroupsVisitor sv(this);
|
||||
node->accept(sv);
|
||||
sv.divide();
|
||||
}
|
||||
@ -178,7 +183,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing CHECK_GEOMETRY"<<std::endl;
|
||||
|
||||
CheckGeometryVisitor mgv;
|
||||
CheckGeometryVisitor mgv(this);
|
||||
node->accept(mgv);
|
||||
}
|
||||
|
||||
@ -186,19 +191,24 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing TRISTRIP_GEOMETRY"<<std::endl;
|
||||
|
||||
TriStripVisitor tsv;
|
||||
TriStripVisitor tsv(this);
|
||||
node->accept(tsv);
|
||||
tsv.stripify();
|
||||
}
|
||||
|
||||
if (options & MERGE_GEOMETRY)
|
||||
{
|
||||
#if 0
|
||||
// temporary compile out while debugging it.
|
||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing MERGE_GEOMETRY"<<std::endl;
|
||||
|
||||
MergeGeometryVisitor mgv;
|
||||
MergeGeometryVisitor mgv(this);
|
||||
node->accept(mgv);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -236,23 +246,48 @@ void Optimizer::StateVisitor::addStateSet(osg::StateSet* stateset,osg::Object* o
|
||||
|
||||
void Optimizer::StateVisitor::apply(osg::Node& node)
|
||||
{
|
||||
|
||||
osg::StateSet* ss = node.getStateSet();
|
||||
if (ss && ss->getDataVariance()==osg::Object::STATIC) addStateSet(ss,&node);
|
||||
if (ss && ss->getDataVariance()==osg::Object::STATIC)
|
||||
{
|
||||
if (isOperationPermissableForObject(&node) &&
|
||||
isOperationPermissableForObject(ss))
|
||||
{
|
||||
addStateSet(ss,&node);
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
void Optimizer::StateVisitor::apply(osg::Geode& geode)
|
||||
{
|
||||
if (!isOperationPermissableForObject(&geode)) return;
|
||||
|
||||
osg::StateSet* ss = geode.getStateSet();
|
||||
if (ss && ss->getDataVariance()==osg::Object::STATIC) addStateSet(ss,&geode);
|
||||
|
||||
|
||||
if (ss && ss->getDataVariance()==osg::Object::STATIC)
|
||||
{
|
||||
if (isOperationPermissableForObject(ss))
|
||||
{
|
||||
addStateSet(ss,&geode);
|
||||
}
|
||||
}
|
||||
for(unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||
{
|
||||
osg::Drawable* drawable = geode.getDrawable(i);
|
||||
if (drawable)
|
||||
{
|
||||
ss = drawable->getStateSet();
|
||||
if (ss && ss->getDataVariance()==osg::Object::STATIC) addStateSet(ss,drawable);
|
||||
if (ss && ss->getDataVariance()==osg::Object::STATIC)
|
||||
{
|
||||
if (isOperationPermissableForObject(drawable) &&
|
||||
isOperationPermissableForObject(ss))
|
||||
{
|
||||
addStateSet(ss,drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -426,9 +461,9 @@ class CollectLowestTransformsVisitor : public osg::NodeVisitor
|
||||
public:
|
||||
|
||||
|
||||
CollectLowestTransformsVisitor():
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
|
||||
|
||||
CollectLowestTransformsVisitor(Optimizer* optimizer=0):
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_optimizer(optimizer) {}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
@ -497,6 +532,11 @@ class CollectLowestTransformsVisitor : public osg::NodeVisitor
|
||||
void disableTransform(osg::Transform* transform);
|
||||
bool removeTransforms(osg::Node* nodeWeCannotRemove);
|
||||
|
||||
inline bool isOperationPermissableForObject(const osg::Object* object) const
|
||||
{
|
||||
return _optimizer ? _optimizer->isOperationPermissableForObject(object,Optimizer::FLATTEN_STATIC_TRANSFORMS) : true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
struct TransformStruct
|
||||
@ -579,6 +619,7 @@ class CollectLowestTransformsVisitor : public osg::NodeVisitor
|
||||
void doTransform(osg::Object* obj,osg::Matrix& matrix);
|
||||
|
||||
|
||||
Optimizer* _optimizer;
|
||||
TransformMap _transformMap;
|
||||
ObjectMap _objectMap;
|
||||
ObjectList _currentObjectList;
|
||||
@ -715,20 +756,21 @@ void CollectLowestTransformsVisitor::setUpMaps()
|
||||
// them that can't be applied, and then disable all objects which have
|
||||
// disabled transforms associated, recursing until all disabled
|
||||
// associativity.
|
||||
// and disable all objects that the operation is not permisable for)
|
||||
for(oitr=_objectMap.begin();
|
||||
oitr!=_objectMap.end();
|
||||
++oitr)
|
||||
{
|
||||
osg::Object* object = oitr->first;
|
||||
ObjectStruct& os = oitr->second;
|
||||
if (os._canBeApplied)
|
||||
{
|
||||
if (os._moreThanOneMatrixRequired)
|
||||
if (os._moreThanOneMatrixRequired || isOperationPermissableForObject(object))
|
||||
{
|
||||
disableObject(oitr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CollectLowestTransformsVisitor::removeTransforms(osg::Node* nodeWeCannotRemove)
|
||||
@ -847,7 +889,7 @@ void Optimizer::FlattenStaticTransformsVisitor::apply(osg::Transform& transform)
|
||||
|
||||
bool Optimizer::FlattenStaticTransformsVisitor::removeTransforms(osg::Node* nodeWeCannotRemove)
|
||||
{
|
||||
CollectLowestTransformsVisitor cltv;
|
||||
CollectLowestTransformsVisitor cltv(_optimizer);
|
||||
|
||||
for(DrawableSet::iterator ditr=_drawableSet.begin();
|
||||
ditr!=_drawableSet.end();
|
||||
@ -1016,7 +1058,7 @@ void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Group& group)
|
||||
{
|
||||
if (group.getNumParents()>0 && group.getNumChildren()<=1)
|
||||
{
|
||||
if (isNodeEmpty(group))
|
||||
if (isNodeEmpty(group) && isOperationPermissableForObject(&group))
|
||||
{
|
||||
_redundantNodeList.insert(&group);
|
||||
}
|
||||
@ -1028,7 +1070,9 @@ void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Group& group)
|
||||
|
||||
void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Transform& transform)
|
||||
{
|
||||
if (transform.getNumParents()>0 && transform.getDataVariance()==osg::Object::STATIC)
|
||||
if (transform.getNumParents()>0 &&
|
||||
transform.getDataVariance()==osg::Object::STATIC &&
|
||||
isOperationPermissableForObject(&transform))
|
||||
{
|
||||
static osg::Matrix identity;
|
||||
osg::Matrix matrix;
|
||||
@ -1087,7 +1131,10 @@ void Optimizer::CombineLODsVisitor::apply(osg::LOD& lod)
|
||||
{
|
||||
if (typeid(*lod.getParent(i))==typeid(osg::Group))
|
||||
{
|
||||
_groupList.insert(lod.getParent(i));
|
||||
if (isOperationPermissableForObject(&lod))
|
||||
{
|
||||
_groupList.insert(lod.getParent(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse(lod);
|
||||
@ -1234,6 +1281,17 @@ struct LessGeometry
|
||||
else if (lhs->getTexCoordIndices(i)) return false;
|
||||
}
|
||||
|
||||
for(unsigned int i=0;i<lhs->getNumVertexAttribArrays();++i)
|
||||
{
|
||||
if (rhs->getVertexAttribArray(i))
|
||||
{
|
||||
if (!lhs->getVertexAttribArray(i)) return true;
|
||||
}
|
||||
else if (lhs->getVertexAttribArray(i)) return false;
|
||||
|
||||
if (rhs->getVertexAttribIndices(i)) { if (!lhs->getVertexAttribIndices(i)) return true; }
|
||||
else if (lhs->getVertexAttribIndices(i)) return false;
|
||||
}
|
||||
|
||||
|
||||
if (lhs->getNormalBinding()==osg::Geometry::BIND_OVERALL)
|
||||
@ -1296,18 +1354,25 @@ struct LessGeometryPrimitiveType
|
||||
|
||||
void Optimizer::CheckGeometryVisitor::checkGeode(osg::Geode& geode)
|
||||
{
|
||||
for(unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||
if (isOperationPermissableForObject(&geode))
|
||||
{
|
||||
osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
|
||||
if (geom)
|
||||
for(unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||
{
|
||||
geom->computeCorrectBindingsAndArraySizes();
|
||||
osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
|
||||
if (geom && isOperationPermissableForObject(geom))
|
||||
{
|
||||
geom->computeCorrectBindingsAndArraySizes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode)
|
||||
{
|
||||
if (!isOperationPermissableForObject(&geode)) return false;
|
||||
|
||||
#if 1
|
||||
|
||||
if (geode.getNumDrawables()>=2)
|
||||
{
|
||||
|
||||
@ -1331,6 +1396,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// don't merge geometry if its above a maximum number of vertices.
|
||||
unsigned int _maximumNumber = 10000;
|
||||
|
||||
@ -1378,6 +1444,8 @@ bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
// convert all polygon primitives which has 3 indices into TRIANGLES, 4 indices into QUADS.
|
||||
unsigned int i;
|
||||
for(i=0;i<geode.getNumDrawables();++i)
|
||||
@ -1574,9 +1642,24 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
||||
}
|
||||
else if (rhs.getVertexArray())
|
||||
{
|
||||
base = 0;
|
||||
lhs.setVertexArray(rhs.getVertexArray());
|
||||
}
|
||||
|
||||
if (lhs.getVertexIndices() && rhs.getVertexIndices())
|
||||
{
|
||||
|
||||
base = lhs.getVertexIndices()->getNumElements();
|
||||
merger.merge(lhs.getVertexIndices(),rhs.getVertexIndices());
|
||||
|
||||
}
|
||||
else if (rhs.getVertexIndices())
|
||||
{
|
||||
base = 0;
|
||||
lhs.setVertexIndices(rhs.getVertexIndices());
|
||||
}
|
||||
|
||||
|
||||
if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getNormalArray(),rhs.getNormalArray());
|
||||
@ -1586,6 +1669,16 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
||||
lhs.setNormalArray(rhs.getNormalArray());
|
||||
}
|
||||
|
||||
if (lhs.getNormalIndices() && rhs.getNormalIndices() && lhs.getNormalBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getNormalIndices(),rhs.getNormalIndices());
|
||||
}
|
||||
else if (rhs.getNormalIndices())
|
||||
{
|
||||
lhs.setNormalIndices(rhs.getNormalIndices());
|
||||
}
|
||||
|
||||
|
||||
if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getColorArray(),rhs.getColorArray());
|
||||
@ -1595,36 +1688,148 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
||||
lhs.setColorArray(rhs.getColorArray());
|
||||
}
|
||||
|
||||
if (lhs.getColorIndices() && rhs.getColorIndices() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getColorIndices(),rhs.getColorIndices());
|
||||
}
|
||||
else if (rhs.getColorIndices())
|
||||
{
|
||||
lhs.setColorIndices(rhs.getColorIndices());
|
||||
}
|
||||
|
||||
if (lhs.getSecondaryColorArray() && rhs.getSecondaryColorArray() && lhs.getSecondaryColorBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getSecondaryColorArray(),rhs.getSecondaryColorArray());
|
||||
}
|
||||
else if (rhs.getColorArray())
|
||||
else if (rhs.getSecondaryColorArray())
|
||||
{
|
||||
lhs.setSecondaryColorArray(rhs.getSecondaryColorArray());
|
||||
}
|
||||
|
||||
if (lhs.getSecondaryColorIndices() && rhs.getSecondaryColorIndices() && lhs.getSecondaryColorBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getSecondaryColorIndices(),rhs.getSecondaryColorIndices());
|
||||
}
|
||||
else if (rhs.getSecondaryColorIndices())
|
||||
{
|
||||
lhs.setSecondaryColorIndices(rhs.getSecondaryColorIndices());
|
||||
}
|
||||
|
||||
if (lhs.getFogCoordArray() && rhs.getFogCoordArray() && lhs.getFogCoordBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getFogCoordArray(),rhs.getFogCoordArray());
|
||||
}
|
||||
else if (rhs.getColorArray())
|
||||
else if (rhs.getFogCoordArray())
|
||||
{
|
||||
lhs.setFogCoordArray(rhs.getFogCoordArray());
|
||||
}
|
||||
|
||||
if (lhs.getFogCoordIndices() && rhs.getFogCoordIndices() && lhs.getFogCoordBinding()!=osg::Geometry::BIND_OVERALL)
|
||||
{
|
||||
merger.merge(lhs.getFogCoordIndices(),rhs.getFogCoordIndices());
|
||||
}
|
||||
else if (rhs.getFogCoordIndices())
|
||||
{
|
||||
lhs.setFogCoordIndices(rhs.getFogCoordIndices());
|
||||
}
|
||||
|
||||
|
||||
for(unsigned int unit=0;unit<lhs.getNumTexCoordArrays();++unit)
|
||||
{
|
||||
merger.merge(lhs.getTexCoordArray(unit),rhs.getTexCoordArray(unit));
|
||||
if (lhs.getTexCoordIndices(unit) && rhs.getTexCoordIndices(unit))
|
||||
{
|
||||
merger.merge(lhs.getTexCoordIndices(unit),rhs.getTexCoordIndices(unit));
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int unit=0;unit<lhs.getNumVertexAttribArrays();++unit)
|
||||
{
|
||||
merger.merge(lhs.getVertexAttribArray(unit),rhs.getVertexAttribArray(unit));
|
||||
if (lhs.getVertexAttribIndices(unit) && rhs.getVertexAttribIndices(unit))
|
||||
{
|
||||
merger.merge(lhs.getVertexAttribIndices(unit),rhs.getVertexAttribIndices(unit));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// shift the indices of the incomming primitives to account for the pre exisiting geometry.
|
||||
for(osg::Geometry::PrimitiveSetList::iterator primItr=rhs.getPrimitiveSetList().begin();
|
||||
primItr!=rhs.getPrimitiveSetList().end();
|
||||
++primItr)
|
||||
{
|
||||
osg::PrimitiveSet* primitive = primItr->get();
|
||||
primitive->offsetIndices(base);
|
||||
switch(primitive->getType())
|
||||
{
|
||||
case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType):
|
||||
{
|
||||
osg::DrawElementsUByte* primitiveUByte = static_cast<osg::DrawElementsUByte*>(primitive);
|
||||
unsigned int currentMaximum = 0;
|
||||
for(osg::DrawElementsUByte::iterator eitr=primitiveUByte->begin();
|
||||
eitr!=primitiveUByte->end();
|
||||
++eitr)
|
||||
{
|
||||
currentMaximum = osg::maximum(currentMaximum,(unsigned int)*eitr);
|
||||
}
|
||||
if ((base+currentMaximum)>=65536)
|
||||
{
|
||||
// must promote to a DrawElementsUInt
|
||||
osg::DrawElementsUInt* new_primitive = new osg::DrawElementsUInt();
|
||||
std::copy(primitiveUByte->begin(),primitiveUByte->end(),std::back_inserter(*new_primitive));
|
||||
new_primitive->offsetIndices(base);
|
||||
(*primItr) = new_primitive;
|
||||
std::cout<<"Remapping to a UInt "<<(*primItr)->className()<<std::endl;
|
||||
} else if ((base+currentMaximum)>=0)
|
||||
{
|
||||
// must promote to a DrawElementsUShort
|
||||
osg::DrawElementsUShort* new_primitive = new osg::DrawElementsUShort();
|
||||
std::copy(primitiveUByte->begin(),primitiveUByte->end(),std::back_inserter(*new_primitive));
|
||||
new_primitive->offsetIndices(base);
|
||||
(*primItr) = new_primitive;
|
||||
std::cout<<"Remapped to a UShort"<<(*primItr)->className()<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"Not Remapping to a UShort"<<std::endl;
|
||||
primitive->offsetIndices(base);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType):
|
||||
{
|
||||
osg::DrawElementsUShort* primitiveUShort = static_cast<osg::DrawElementsUShort*>(primitive);
|
||||
unsigned int currentMaximum = 0;
|
||||
for(osg::DrawElementsUShort::iterator eitr=primitiveUShort->begin();
|
||||
eitr!=primitiveUShort->end();
|
||||
++eitr)
|
||||
{
|
||||
currentMaximum = osg::maximum(currentMaximum,(unsigned int)*eitr);
|
||||
}
|
||||
if ((base+currentMaximum)>=65536)
|
||||
{
|
||||
// must promote to a DrawElementsUInt
|
||||
osg::DrawElementsUInt* new_primitive = new osg::DrawElementsUInt();
|
||||
std::copy(primitiveUShort->begin(),primitiveUShort->end(),std::back_inserter(*new_primitive));
|
||||
new_primitive->offsetIndices(base);
|
||||
(*primItr) = new_primitive;
|
||||
}
|
||||
else
|
||||
{
|
||||
primitive->offsetIndices(base);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case(osg::PrimitiveSet::DrawArraysPrimitiveType):
|
||||
case(osg::PrimitiveSet::DrawArrayLengthsPrimitiveType):
|
||||
case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType):
|
||||
default:
|
||||
primitive->offsetIndices(base);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
lhs.getPrimitiveSetList().insert(lhs.getPrimitiveSetList().end(),
|
||||
@ -1686,7 +1891,10 @@ void Optimizer::SpatializeGroupsVisitor::apply(osg::Group& group)
|
||||
{
|
||||
if (typeid(group)==typeid(osg::Group) || group.asTransform())
|
||||
{
|
||||
_groupsToDivideList.insert(&group);
|
||||
if (isOperationPermissableForObject(&group))
|
||||
{
|
||||
_groupsToDivideList.insert(&group);
|
||||
}
|
||||
}
|
||||
traverse(group);
|
||||
}
|
||||
@ -1872,7 +2080,7 @@ bool Optimizer::SpatializeGroupsVisitor::divide(osg::Group* group, unsigned int
|
||||
|
||||
void Optimizer::CopySharedSubgraphsVisitor::apply(osg::Node& node)
|
||||
{
|
||||
if (node.getNumParents()>1)
|
||||
if (node.getNumParents()>1 && !isOperationPermissableForObject(&node))
|
||||
{
|
||||
_sharedNodeList.insert(&node);
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ void TriStripVisitor::stripify(Geometry& geom)
|
||||
if (geom.suitableForOptimization())
|
||||
{
|
||||
// removing coord indices
|
||||
std::cout<<"Removing attribute indices"<<std::endl;
|
||||
osg::notify(osg::INFO)<<"TriStripVisitor::stripify(Geometry&): Removing attribute indices"<<std::endl;
|
||||
geom.copyToAndOptimize(geom);
|
||||
}
|
||||
|
||||
@ -685,13 +685,13 @@ void TriStripVisitor::stripify(Geometry& geom)
|
||||
float minimum_ratio_of_indices_to_unique_vertices = 1;
|
||||
float ratio_of_indices_to_unique_vertices = ((float)taf._in_indices.size()/(float)numUnique);
|
||||
|
||||
std::cout<<"Number of indices"<<taf._in_indices.size()<<" numUnique"<< numUnique << std::endl;
|
||||
std::cout<<" ratio indices/numUnique"<< ratio_of_indices_to_unique_vertices << std::endl;
|
||||
osg::notify(osg::INFO)<<"TriStripVisitor::stripify(Geometry&): Number of indices"<<taf._in_indices.size()<<" numUnique"<< numUnique << std::endl;
|
||||
osg::notify(osg::INFO)<<"TriStripVisitor::stripify(Geometry&): ratio indices/numUnique"<< ratio_of_indices_to_unique_vertices << std::endl;
|
||||
|
||||
// only tri strip if there is point in doing so.
|
||||
if (!taf._in_indices.empty() && ratio_of_indices_to_unique_vertices>=minimum_ratio_of_indices_to_unique_vertices)
|
||||
{
|
||||
std::cout<<" doing tri strip"<< std::endl;
|
||||
osg::notify(osg::INFO)<<"TriStripVisitor::stripify(Geometry&): doing tri strip"<< std::endl;
|
||||
|
||||
unsigned int in_numVertices = 0;
|
||||
for(triangle_stripper::tri_stripper::indices::iterator itr=taf._in_indices.begin();
|
||||
@ -872,7 +872,7 @@ void TriStripVisitor::stripify(Geometry& geom)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<" not doing tri strip *****************"<< std::endl;
|
||||
osg::notify(osg::INFO)<<"TriStripVisitor::stripify(Geometry&): not doing tri strip *****************"<< std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user