diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index e1602223a..dbdff4ea5 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -1618,7 +1618,7 @@ void Optimizer::CombineLODsVisitor::combineLODs() struct LessGeometry { - bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) const + bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { if (lhs->getStateSet()getStateSet()) return true; if (rhs->getStateSet()getStateSet()) return false; @@ -1714,7 +1714,7 @@ struct LessGeometry struct LessGeometryPrimitiveType { - bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) const + bool operator() (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) const { for(unsigned int i=0; igetNumPrimitiveSets() && igetNumPrimitiveSets(); @@ -1792,45 +1792,39 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) if (group.getNumChildren()>=2) { - typedef std::vector DuplicateList; - typedef std::vector< osg::ref_ptr > DrawableList; - typedef std::map GeometryDuplicateMap; + typedef std::vector< osg::ref_ptr > DuplicateList; + typedef std::vector< osg::ref_ptr > Nodes; + typedef std::map< osg::ref_ptr ,DuplicateList,LessGeometry> GeometryDuplicateMap; typedef std::vector MergeList; GeometryDuplicateMap geometryDuplicateMap; - DrawableList standardDrawables; + Nodes standardChildren; unsigned int i; for(i=0;iasDrawable(); - if (drawable) + osg::Node* child = group.getChild(i); + osg::Geometry* geom = child->asGeometry(); + if (geom) { - osg::Geometry* geom = drawable->asGeometry(); - if (geom) + if (!geometryContainsSharedArrays(*geom) && + geom->getDataVariance()!=osg::Object::DYNAMIC && + isOperationPermissibleForObject(geom)) { - //geom->computeCorrectBindingsAndArraySizes(); - - if (!geometryContainsSharedArrays(*geom) && - geom->getDataVariance()!=osg::Object::DYNAMIC && - isOperationPermissibleForObject(geom)) - { - geometryDuplicateMap[geom].push_back(geom); - } - else - { - standardDrawables.push_back(drawable); - } + geometryDuplicateMap[geom].push_back(geom); } else { - standardDrawables.push_back(drawable); + standardChildren.push_back(geom); } } + else + { + standardChildren.push_back(child); + } } -#if 1 // first try to group geometries with the same properties // (i.e. array types) to avoid loss of data during merging MergeList mergeListChecked; // List of drawables just before merging, grouped by "compatibility" and vertex limit @@ -1860,7 +1854,7 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) dupItr!=itr->second.end(); ++dupItr) { - osg::Geometry* geomToPush = *dupItr; + osg::Geometry* geomToPush = dupItr->get(); // try to group geomToPush with another geometry MergeList::iterator eachMergeList=mergeListTmp.begin(); @@ -1946,6 +1940,16 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) if (needToDoMerge) { + // to avoid performance issues associated with incrementally removing a large number children, we remove them all and add back the ones we need. + group.removeChildren(0, group.getNumChildren()); + + for(Nodes::iterator itr = standardChildren.begin(); + itr != standardChildren.end(); + ++itr) + { + group.addChild(*itr); + } + // now do the merging of geometries for(MergeList::iterator mitr = mergeList.begin(); mitr != mergeList.end(); @@ -1954,65 +1958,18 @@ bool Optimizer::MergeGeometryVisitor::mergeGroup(osg::Group& group) DuplicateList& duplicateList = *mitr; if (duplicateList.size()>1) { - osg::Geometry* lhs = duplicateList.front(); + osg::ref_ptr lhs = duplicateList.front(); + group.addChild(lhs.get()); + for(DuplicateList::iterator ditr = duplicateList.begin()+1; ditr != duplicateList.end(); ++ditr) { - mergeGeometry(*lhs,**ditr); - - group.removeChild(*ditr); + mergeGeometry(*lhs, **ditr); } } } } - -#else - // don't merge geometry if its above a maximum number of vertices. - for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin(); - itr!=geometryDuplicateMap.end(); - ++itr) - { - if (itr->second.size()>1) - { - std::sort(itr->second.begin(),itr->second.end(),LessGeometryPrimitiveType()); - osg::Geometry* lhs = itr->second[0]; - for(DuplicateList::iterator dupItr=itr->second.begin()+1; - dupItr!=itr->second.end(); - ++dupItr) - { - - osg::Geometry* rhs = *dupItr; - - if (lhs->getVertexArray() && lhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices) - { - lhs = rhs; - continue; - } - - if (rhs->getVertexArray() && rhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices) - { - continue; - } - - if (lhs->getVertexArray() && rhs->getVertexArray() && - (lhs->getVertexArray()->getNumElements()+rhs->getVertexArray()->getNumElements())>=_targetMaximumNumberOfVertices) - { - continue; - } - - if (mergeGeometry(*lhs,*rhs)) - { - geode.removeDrawable(rhs); - - static int co = 0; - OSG_INFO<<"merged and removed Geometry "<<++co<