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:
Robert Osfield 2003-12-11 23:26:22 +00:00
parent 5295d68fd3
commit 1881610a35
4 changed files with 383 additions and 55 deletions

View File

@ -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;
};
};

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}