Added StatsVisitor to include/osg/Statistics, and usage of it in osgUtil::Optimizer.
Added --optimize <string> option to osgconv
This commit is contained in:
parent
541433c7be
commit
dd32e6425e
@ -450,6 +450,18 @@ int main( int argc, char **argv )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string options;
|
||||||
|
while(arguments.read("--optimizer",options))
|
||||||
|
{
|
||||||
|
osg::notify(osg::NOTICE)<<"Setting "<<options<<std::endl;
|
||||||
|
setenv("OSG_OPTIMIZER",options.c_str(),1);
|
||||||
|
|
||||||
|
char* result = getenv("OSG_OPTIMIZER");
|
||||||
|
if (result) osg::notify(osg::NOTICE)<<"Got value "<<result<<std::endl;
|
||||||
|
else osg::notify(osg::NOTICE)<<"No value"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FileNameList fileNames;
|
FileNameList fileNames;
|
||||||
OrientationConverter oc;
|
OrientationConverter oc;
|
||||||
bool do_convert = false;
|
bool do_convert = false;
|
||||||
|
@ -16,8 +16,16 @@
|
|||||||
|
|
||||||
#include <osg/PrimitiveSet>
|
#include <osg/PrimitiveSet>
|
||||||
#include <osg/Drawable>
|
#include <osg/Drawable>
|
||||||
|
#include <osg/NodeVisitor>
|
||||||
|
#include <osg/Geode>
|
||||||
|
#include <osg/LOD>
|
||||||
|
#include <osg/Switch>
|
||||||
|
#include <osg/Geometry>
|
||||||
|
#include <osg/Transform>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace osgUtil {
|
namespace osgUtil {
|
||||||
|
|
||||||
@ -197,6 +205,167 @@ inline unsigned int Statistics::_calculate_primitives_number_by_mode(GLenum mode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** StatsVisitor for collecting statistics about scene graph.*/
|
||||||
|
class StatsVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::set<osg::Node*> NodeSet;
|
||||||
|
typedef std::set<osg::Drawable*> DrawableSet;
|
||||||
|
|
||||||
|
StatsVisitor():
|
||||||
|
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||||
|
_numInstancedGroup(0),
|
||||||
|
_numInstancedSwitch(0),
|
||||||
|
_numInstancedLOD(0),
|
||||||
|
_numInstancedTransform(0),
|
||||||
|
_numInstancedGeode(0),
|
||||||
|
_numInstancedDrawable(0),
|
||||||
|
_numInstancedGeometry(0) {}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
_numInstancedGroup = 0;
|
||||||
|
_numInstancedSwitch = 0;
|
||||||
|
_numInstancedLOD = 0;
|
||||||
|
_numInstancedTransform = 0;
|
||||||
|
_numInstancedGeode = 0;
|
||||||
|
_numInstancedDrawable = 0;
|
||||||
|
_numInstancedGeometry = 0;
|
||||||
|
|
||||||
|
_groupSet.clear();
|
||||||
|
_transformSet.clear();
|
||||||
|
_lodSet.clear();
|
||||||
|
_switchSet.clear();
|
||||||
|
_geodeSet.clear();
|
||||||
|
_drawableSet.clear();
|
||||||
|
_geometrySet.clear();
|
||||||
|
|
||||||
|
_uniqueStats.reset();
|
||||||
|
_instancedStats.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Group& node)
|
||||||
|
{
|
||||||
|
++_numInstancedGroup;
|
||||||
|
_groupSet.insert(&node);
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Transform& node)
|
||||||
|
{
|
||||||
|
++_numInstancedTransform;
|
||||||
|
_transformSet.insert(&node);
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::LOD& node)
|
||||||
|
{
|
||||||
|
++_numInstancedLOD;
|
||||||
|
_lodSet.insert(&node);
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Switch& node)
|
||||||
|
{
|
||||||
|
++_numInstancedSwitch;
|
||||||
|
_switchSet.insert(&node);
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Geode& node)
|
||||||
|
{
|
||||||
|
++_numInstancedGeode;
|
||||||
|
_geodeSet.insert(&node);
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<node.getNumDrawables();++i)
|
||||||
|
{
|
||||||
|
apply(*node.getDrawable(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(osg::Drawable& drawable)
|
||||||
|
{
|
||||||
|
++_numInstancedDrawable;
|
||||||
|
|
||||||
|
drawable.accept(_instancedStats);
|
||||||
|
|
||||||
|
_drawableSet.insert(&drawable);
|
||||||
|
|
||||||
|
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(&drawable);
|
||||||
|
if (geometry)
|
||||||
|
{
|
||||||
|
++_numInstancedGeometry;
|
||||||
|
_geometrySet.insert(geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void totalUpStats()
|
||||||
|
{
|
||||||
|
_uniqueStats.reset();
|
||||||
|
|
||||||
|
for(DrawableSet::iterator itr = _drawableSet.begin();
|
||||||
|
itr != _drawableSet.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
(*itr)->accept(_uniqueStats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(std::ostream& out)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned int unique_primitives = 0;
|
||||||
|
osgUtil::Statistics::PrimitiveCountMap::iterator pcmitr;
|
||||||
|
for(pcmitr = _uniqueStats.GetPrimitivesBegin();
|
||||||
|
pcmitr != _uniqueStats.GetPrimitivesEnd();
|
||||||
|
++pcmitr)
|
||||||
|
{
|
||||||
|
unique_primitives += pcmitr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int instanced_primitives = 0;
|
||||||
|
for(pcmitr = _instancedStats.GetPrimitivesBegin();
|
||||||
|
pcmitr != _instancedStats.GetPrimitivesEnd();
|
||||||
|
++pcmitr)
|
||||||
|
{
|
||||||
|
instanced_primitives += pcmitr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
out<<"Object Type\t#Unique\t#Instanced"<<std::endl;
|
||||||
|
out<<"Group \t"<<_groupSet.size()<<"\t"<<_numInstancedGroup<<std::endl;
|
||||||
|
out<<"Transform \t"<<_transformSet.size()<<"\t"<<_numInstancedTransform<<std::endl;
|
||||||
|
out<<"LOD \t"<<_lodSet.size()<<"\t"<<_numInstancedLOD<<std::endl;
|
||||||
|
out<<"Switch \t"<<_switchSet.size()<<"\t"<<_numInstancedSwitch<<std::endl;
|
||||||
|
out<<"Geode \t"<<_geodeSet.size()<<"\t"<<_numInstancedGeode<<std::endl;
|
||||||
|
out<<"Drawable \t"<<_drawableSet.size()<<"\t"<<_numInstancedDrawable<<std::endl;
|
||||||
|
out<<"Geometry \t"<<_geometrySet.size()<<"\t"<<_numInstancedGeometry<<std::endl;
|
||||||
|
out<<"Vertices \t"<<_uniqueStats._vertexCount<<"\t"<<_instancedStats._vertexCount<<std::endl;
|
||||||
|
out<<"Primitives \t"<<unique_primitives<<"\t"<<instanced_primitives<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int _numInstancedGroup;
|
||||||
|
unsigned int _numInstancedSwitch;
|
||||||
|
unsigned int _numInstancedLOD;
|
||||||
|
unsigned int _numInstancedTransform;
|
||||||
|
unsigned int _numInstancedGeode;
|
||||||
|
unsigned int _numInstancedDrawable;
|
||||||
|
unsigned int _numInstancedGeometry;
|
||||||
|
|
||||||
|
NodeSet _groupSet;
|
||||||
|
NodeSet _transformSet;
|
||||||
|
NodeSet _lodSet;
|
||||||
|
NodeSet _switchSet;
|
||||||
|
NodeSet _geodeSet;
|
||||||
|
DrawableSet _drawableSet;
|
||||||
|
DrawableSet _geometrySet;
|
||||||
|
|
||||||
|
osgUtil::Statistics _uniqueStats;
|
||||||
|
osgUtil::Statistics _instancedStats;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <osgUtil/TransformAttributeFunctor>
|
#include <osgUtil/TransformAttributeFunctor>
|
||||||
#include <osgUtil/TriStripVisitor>
|
#include <osgUtil/TriStripVisitor>
|
||||||
#include <osgUtil/Tesselator>
|
#include <osgUtil/Tesselator>
|
||||||
|
#include <osgUtil/Statistics>
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -38,23 +39,22 @@
|
|||||||
using namespace osgUtil;
|
using namespace osgUtil;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Optimizer::reset()
|
void Optimizer::reset()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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 | REMOVE_LOADED_PROXY_NODES | TESSELATE_GEOMETRY | CHECK_GEOMETRY");
|
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 | MERGE_GEODES | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS | REMOVE_LOADED_PROXY_NODES | TESSELATE_GEOMETRY | CHECK_GEOMETRY");
|
||||||
|
|
||||||
void Optimizer::optimize(osg::Node* node)
|
void Optimizer::optimize(osg::Node* node)
|
||||||
{
|
{
|
||||||
unsigned int options = 0;
|
unsigned int options = 0;
|
||||||
|
|
||||||
|
|
||||||
const char* env = getenv("OSG_OPTIMIZER");
|
const char* env = getenv("OSG_OPTIMIZER");
|
||||||
if (env)
|
if (env)
|
||||||
{
|
{
|
||||||
std::string str(env);
|
std::string str(env);
|
||||||
|
|
||||||
|
|
||||||
if(str.find("OFF")!=std::string::npos) options = 0;
|
if(str.find("OFF")!=std::string::npos) options = 0;
|
||||||
|
|
||||||
if(str.find("~DEFAULT")!=std::string::npos) options ^= DEFAULT_OPTIMIZATIONS;
|
if(str.find("~DEFAULT")!=std::string::npos) options ^= DEFAULT_OPTIMIZATIONS;
|
||||||
@ -106,10 +106,21 @@ void Optimizer::optimize(osg::Node* node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
optimize(node,options);
|
optimize(node,options);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Optimizer::optimize(osg::Node* node, unsigned int options)
|
void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||||
{
|
{
|
||||||
|
StatsVisitor stats;
|
||||||
|
|
||||||
|
if (osg::getNotifyLevel()>=osg::INFO)
|
||||||
|
{
|
||||||
|
node->accept(stats);
|
||||||
|
stats.totalUpStats();
|
||||||
|
osg::notify(osg::NOTICE)<<std::endl<<"Stats before:"<<std::endl;
|
||||||
|
stats.print(osg::notify(osg::NOTICE));
|
||||||
|
}
|
||||||
|
|
||||||
if (options & TESSELATE_GEOMETRY)
|
if (options & TESSELATE_GEOMETRY)
|
||||||
{
|
{
|
||||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing TESSELATE_GEOMETRY"<<std::endl;
|
osg::notify(osg::INFO)<<"Optimizer::optimize() doing TESSELATE_GEOMETRY"<<std::endl;
|
||||||
@ -189,20 +200,6 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (options & REMOVE_REDUNDANT_NODES)
|
|
||||||
{
|
|
||||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing REMOVE_REDUNDANT_NODES"<<std::endl;
|
|
||||||
|
|
||||||
RemoveEmptyNodesVisitor renv(this);
|
|
||||||
node->accept(renv);
|
|
||||||
renv.removeEmptyNodes();
|
|
||||||
|
|
||||||
RemoveRedundantNodesVisitor rrnv(this);
|
|
||||||
node->accept(rrnv);
|
|
||||||
rrnv.removeRedundantNodes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options & MERGE_GEODES)
|
if (options & MERGE_GEODES)
|
||||||
{
|
{
|
||||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing MERGE_GEODES"<<std::endl;
|
osg::notify(osg::INFO)<<"Optimizer::optimize() doing MERGE_GEODES"<<std::endl;
|
||||||
@ -237,6 +234,20 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
|||||||
tsv.stripify();
|
tsv.stripify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options & REMOVE_REDUNDANT_NODES)
|
||||||
|
{
|
||||||
|
osg::notify(osg::INFO)<<"Optimizer::optimize() doing REMOVE_REDUNDANT_NODES"<<std::endl;
|
||||||
|
|
||||||
|
RemoveEmptyNodesVisitor renv(this);
|
||||||
|
node->accept(renv);
|
||||||
|
renv.removeEmptyNodes();
|
||||||
|
|
||||||
|
RemoveRedundantNodesVisitor rrnv(this);
|
||||||
|
node->accept(rrnv);
|
||||||
|
rrnv.removeRedundantNodes();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (options & SPATIALIZE_GROUPS)
|
if (options & SPATIALIZE_GROUPS)
|
||||||
{
|
{
|
||||||
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SPATIALIZE_GROUPS"<<std::endl;
|
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SPATIALIZE_GROUPS"<<std::endl;
|
||||||
@ -246,6 +257,14 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
|||||||
sv.divide();
|
sv.divide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (osg::getNotifyLevel()>=osg::INFO)
|
||||||
|
{
|
||||||
|
stats.reset();
|
||||||
|
node->accept(stats);
|
||||||
|
stats.totalUpStats();
|
||||||
|
osg::notify(osg::NOTICE)<<std::endl<<"Stats after:"<<std::endl;
|
||||||
|
stats.print(osg::notify(osg::NOTICE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2533,11 +2552,16 @@ bool Optimizer::MergeGeodesVisitor::mergeGeodes(osg::Group& group)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (geodeDuplicateMap.empty()) return false;
|
||||||
|
|
||||||
|
// osg::notify(osg::NOTICE)<<"mergeGeodes in group '"<<group.getName()<<"' "<<geodeDuplicateMap.size()<<std::endl;
|
||||||
|
|
||||||
// merge
|
// merge
|
||||||
for(GeodeDuplicateMap::iterator itr=geodeDuplicateMap.begin();
|
for(GeodeDuplicateMap::iterator itr=geodeDuplicateMap.begin();
|
||||||
itr!=geodeDuplicateMap.end();
|
itr!=geodeDuplicateMap.end();
|
||||||
++itr)
|
++itr)
|
||||||
{
|
{
|
||||||
|
// osg::notify(osg::NOTICE)<<" "<<itr->second.size()<<std::endl;
|
||||||
if (itr->second.size()>1)
|
if (itr->second.size()>1)
|
||||||
{
|
{
|
||||||
osg::Geode* lhs = itr->second[0];
|
osg::Geode* lhs = itr->second[0];
|
||||||
@ -2556,6 +2580,9 @@ bool Optimizer::MergeGeodesVisitor::mergeGeodes(osg::Group& group)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user