diff --git a/components/sceneutil/optimizer.cpp b/components/sceneutil/optimizer.cpp index 510f05fbd..812a5ae6a 100644 --- a/components/sceneutil/optimizer.cpp +++ b/components/sceneutil/optimizer.cpp @@ -109,6 +109,8 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) node->accept(rrnv); rrnv.removeRedundantNodes(); + MergeGroupsVisitor mgrp(this); + node->accept(mgrp); } if (options & VERTEX_POSTTRANSFORM) @@ -1807,4 +1809,55 @@ bool Optimizer::MergeGeometryVisitor::mergePrimitive(osg::DrawElementsUInt& lhs, return true; } + + +bool Optimizer::MergeGroupsVisitor::isOperationPermissible(osg::Group& node) +{ + return !node.asTransform() && + !node.getCullCallback() && + !node.getEventCallback() && + !node.getUpdateCallback() && + isOperationPermissibleForObject(&node); +} + +void Optimizer::MergeGroupsVisitor::apply(osg::Group &group) +{ + if (group.getNumChildren() <= 1) + traverse(group); + else + { + typedef std::map > GroupMap; + GroupMap childGroups; + for (unsigned int i=0; iasGroup(); + if (childGroup && isOperationPermissible(*childGroup)) + { + childGroups[childGroup->getStateSet()].insert(childGroup); + } + } + + for (GroupMap::iterator it = childGroups.begin(); it != childGroups.end(); ++it) + { + const std::set& groupSet = it->second; + if (groupSet.size() <= 1) + continue; + else + { + osg::Group* first = *groupSet.begin(); + for (std::set::const_iterator groupIt = ++groupSet.begin(); groupIt != groupSet.end(); ++groupIt) + { + osg::Group* toMerge = *groupIt; + for (unsigned int i=0; igetNumChildren(); ++i) + first->addChild(toMerge->getChild(i)); + toMerge->removeChildren(0, toMerge->getNumChildren()); + group.removeChild(toMerge); + } + } + } + traverse(group); + } +} + } diff --git a/components/sceneutil/optimizer.hpp b/components/sceneutil/optimizer.hpp index d2a63a32a..b43a339ca 100644 --- a/components/sceneutil/optimizer.hpp +++ b/components/sceneutil/optimizer.hpp @@ -346,6 +346,20 @@ class Optimizer }; + /** Merge adjacent Groups that have the same StateSet. */ + class MergeGroupsVisitor : public SceneUtil::BaseOptimizerVisitor + { + public: + MergeGroupsVisitor(SceneUtil::Optimizer* optimizer) + : BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) + { + } + + bool isOperationPermissible(osg::Group& node); + + virtual void apply(osg::Group& group); + }; + class MergeGeometryVisitor : public BaseOptimizerVisitor { public: