Added Optimizer::FlattenBillboardsVisitor.

This commit is contained in:
Robert Osfield 2006-07-18 11:03:46 +00:00
parent e016cdafb2
commit a74801a0ee
3 changed files with 139 additions and 4 deletions

View File

@ -76,6 +76,7 @@ class OSGUTIL_EXPORT Optimizer
TRISTRIP_GEOMETRY = 0x200,
TESSELATE_GEOMETRY = 0x400,
OPTIMIZE_TEXTURE_SETTINGS = 0x800,
FLATTEN_BILLBOARDS = 0x1000,
DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
REMOVE_REDUNDANT_NODES |
REMOVE_LOADED_PROXY_NODES |
@ -546,6 +547,26 @@ class OSGUTIL_EXPORT Optimizer
};
/** Flatten MatrixTransform/Billboard pairs.*/
class OSGUTIL_EXPORT FlattenBillboardVisitor : public BaseOptimizerVisitor
{
public:
FlattenBillboardVisitor(Optimizer* optimizer=0):
BaseOptimizerVisitor(optimizer, FLATTEN_BILLBOARDS) {}
typedef std::vector<osg::NodePath> NodePathList;
typedef std::map<osg::Billboard*, NodePathList > BillboardNodePathMap;
virtual void reset();
virtual void apply(osg::Billboard& billboard);
void process();
BillboardNodePathMap _billboards;
};
};
inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const

View File

@ -49,7 +49,7 @@ Geode::~Geode()
bool Geode::addDrawable( Drawable *drawable )
{
if (drawable && !containsDrawable(drawable))
if (drawable /* && !containsDrawable(drawable)*/)
{
// note ref_ptr<> automatically handles incrementing drawable's reference count.
_drawables.push_back(drawable);

View File

@ -27,6 +27,7 @@
#include <osg/PagedLOD>
#include <osg/ProxyNode>
#include <osg/Timer>
#include <osg/io_utils>
#include <osgUtil/TransformAttributeFunctor>
#include <osgUtil/TriStripVisitor>
@ -114,7 +115,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
{
StatsVisitor stats;
if (osg::getNotifyLevel()>=osg::INFO)
// if (osg::getNotifyLevel()>=osg::INFO)
{
node->accept(stats);
stats.totalUpStats();
@ -199,7 +200,6 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
cstv.removeTransforms(node);
}
if (options & MERGE_GEODES)
{
@ -261,6 +261,13 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
}
if (options & FLATTEN_BILLBOARDS)
{
FlattenBillboardVisitor fbv(this);
node->accept(fbv);
fbv.process();
}
if (options & SPATIALIZE_GROUPS)
{
osg::notify(osg::INFO)<<"Optimizer::optimize() doing SPATIALIZE_GROUPS"<<std::endl;
@ -270,7 +277,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
sv.divide();
}
if (osg::getNotifyLevel()>=osg::INFO)
// if (osg::getNotifyLevel()>=osg::INFO)
{
stats.reset();
node->accept(stats);
@ -2831,3 +2838,110 @@ bool Optimizer::MergeGeodesVisitor::mergeGeode(osg::Geode& lhs, osg::Geode& rhs)
return true;
}
////////////////////////////////////////////////////////////////////////////
// FlattenBillboardVisitor
////////////////////////////////////////////////////////////////////////////
void Optimizer::FlattenBillboardVisitor::reset()
{
_billboards.clear();
}
void Optimizer::FlattenBillboardVisitor::apply(osg::Billboard& billboard)
{
_billboards[&billboard].push_back(getNodePath());
}
void Optimizer::FlattenBillboardVisitor::process()
{
for(BillboardNodePathMap::iterator itr = _billboards.begin();
itr != _billboards.end();
++itr)
{
bool mergeAcceptable = true;
osg::ref_ptr<osg::Billboard> billboard = itr->first;
NodePathList& npl = itr->second;
osg::Group* mainGroup = 0;
if (npl.size()>1)
{
for(NodePathList::iterator nitr = npl.begin();
nitr != npl.end();
++nitr)
{
osg::NodePath& np = *nitr;
if (np.size()>=3)
{
osg::Group* group = dynamic_cast<osg::Group*>(np[np.size()-3]);
if (mainGroup==0) mainGroup = group;
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(np[np.size()-2]);
if (group == mainGroup &&
np[np.size()-1]==billboard.get() &&
mt && mt->getDataVariance()==osg::Object::STATIC &&
mt->getNumChildren()==1)
{
const osg::Matrix& m = mt->getMatrix();
mergeAcceptable = (m(0,0)==1.0 && m(0,1)==0.0 && m(0,2)==0.0 && m(0,3)==0.0 &&
m(1,0)==0.0 && m(1,1)==1.0 && m(1,2)==0.0 && m(1,3)==0.0 &&
m(2,0)==0.0 && m(2,1)==0.0 && m(2,2)==1.0 && m(2,3)==0.0 &&
m(3,3)==1.0);
}
else
{
mergeAcceptable = false;
}
}
else
{
mergeAcceptable = false;
}
}
}
else
{
mergeAcceptable = false;
}
if (mergeAcceptable)
{
osg::Billboard* new_billboard = new osg::Billboard;
new_billboard->setMode(billboard->getMode());
new_billboard->setAxis(billboard->getAxis());
new_billboard->setStateSet(billboard->getStateSet());
new_billboard->setName(billboard->getName());
mainGroup->addChild(new_billboard);
typedef std::set<osg::MatrixTransform*> MatrixTransformSet;
MatrixTransformSet mts;
for(NodePathList::iterator nitr = npl.begin();
nitr != npl.end();
++nitr)
{
osg::NodePath& np = *nitr;
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(np[np.size()-2]);
mts.insert(mt);
}
for(MatrixTransformSet::iterator mitr = mts.begin();
mitr != mts.end();
++mitr)
{
osg::MatrixTransform* mt = *mitr;
for(unsigned int i=0; i<billboard->getNumDrawables(); ++i)
{
new_billboard->addDrawable(billboard->getDrawable(i),
billboard->getPosition(i)*mt->getMatrix());
}
mainGroup->removeChild(mt);
}
}
}
}