From a74801a0eeab71813798bba4f5fbec1774963637 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 18 Jul 2006 11:03:46 +0000 Subject: [PATCH] Added Optimizer::FlattenBillboardsVisitor. --- include/osgUtil/Optimizer | 21 +++++++ src/osg/Geode.cpp | 2 +- src/osgUtil/Optimizer.cpp | 120 +++++++++++++++++++++++++++++++++++++- 3 files changed, 139 insertions(+), 4 deletions(-) diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index 0f1b804c2..be4202e46 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -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 NodePathList; + typedef std::map BillboardNodePathMap; + + virtual void reset(); + + virtual void apply(osg::Billboard& billboard); + + void process(); + + BillboardNodePathMap _billboards; + + }; + }; inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const diff --git a/src/osg/Geode.cpp b/src/osg/Geode.cpp index 436b437c3..258f51e64 100644 --- a/src/osg/Geode.cpp +++ b/src/osg/Geode.cpp @@ -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); diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 3a0a6c331..13d6b2697 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -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"<=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 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(np[np.size()-3]); + if (mainGroup==0) mainGroup = group; + + osg::MatrixTransform* mt = dynamic_cast(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 MatrixTransformSet; + MatrixTransformSet mts; + + for(NodePathList::iterator nitr = npl.begin(); + nitr != npl.end(); + ++nitr) + { + osg::NodePath& np = *nitr; + osg::MatrixTransform* mt = dynamic_cast(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; igetNumDrawables(); ++i) + { + new_billboard->addDrawable(billboard->getDrawable(i), + billboard->getPosition(i)*mt->getMatrix()); + } + mainGroup->removeChild(mt); + } + } + } + +} +