From e835ea53287784a9871be5bfb2d51c6435571ba0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 14 Jul 2006 11:04:24 +0000 Subject: [PATCH] Speeded up merge geometry --- src/osgUtil/Optimizer.cpp | 221 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 10 deletions(-) diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index b196127d3..d2eb425fb 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -203,7 +203,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) if (options & MERGE_GEODES) { - osg::notify(osg::INFO)<<"Optimizer::optimize() doing MERGE_GEODES"<tick(); @@ -212,7 +212,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) osg::Timer_t endTick = osg::Timer::instance()->tick(); - osg::notify(osg::INFO)<<"MERGE_GEODES took "<delta_s(startTick,endTick)<delta_s(startTick,endTick)<tick(); @@ -235,7 +235,7 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) osg::Timer_t endTick = osg::Timer::instance()->tick(); - osg::notify(osg::INFO)<<"MERGE_GEOMETRY took "<delta_s(startTick,endTick)<delta_s(startTick,endTick)<=2) { + // osg::notify(osg::NOTICE)<<"Before "< DuplicateList; typedef std::map GeometryDuplicateMap; + typedef std::vector MergeList; + GeometryDuplicateMap geometryDuplicateMap; + osg::Geode::DrawableList standardDrawables; unsigned int i; for(i=0;isecond.size()>1) + { + std::sort(itr->second.begin(),itr->second.end(),LessGeometryPrimitiveType()); + osg::Geometry* lhs = itr->second[0]; + duplicateList->push_back(lhs); + + unsigned int numVertices = lhs->getVertexArray() ? lhs->getVertexArray()->getNumElements() : 0; + + for(DuplicateList::iterator dupItr=itr->second.begin()+1; + dupItr!=itr->second.end(); + ++dupItr) + { + + osg::Geometry* rhs = *dupItr; + + unsigned int numRhsVertices = rhs->getVertexArray() ? rhs->getVertexArray()->getNumElements() : 0; + + if (numVertices+numRhsVertices < _targetMaximumNumberOfVertices) + { + duplicateList->push_back(rhs); + numVertices += numRhsVertices; + needToDoMerge = true; + } + else + { + numVertices = numRhsVertices; + mergeList.push_back(DuplicateList()); + duplicateList = &mergeList.back(); + duplicateList->push_back(rhs); + } + + } + } + else if (itr->second.size()>0) + { + duplicateList->push_back(itr->second[0]); + } + } + + if (needToDoMerge) + { + // first take a reference to all the drawables to prevent them being deleted prematurely + osg::Geode::DrawableList keepDrawables; + keepDrawables.resize(geode.getNumDrawables()); + for(i=0; iget()); + } + + // now do the merging of geometries + for(MergeList::iterator mitr = mergeList.begin(); + mitr != mergeList.end(); + ++mitr) + { + DuplicateList& duplicateList = *mitr; + if (duplicateList.size()>1) + { + osg::Geometry* lhs = duplicateList.front(); + geode.addDrawable(lhs); + for(DuplicateList::iterator ditr = duplicateList.begin()+1; + ditr != duplicateList.end(); + ++ditr) + { + mergeGeometry(*lhs,**ditr); + } + } + else if (duplicateList.size()>0) + { + geode.addDrawable(duplicateList.front()); + } + } + } + +#else // don't merge geometry if its above a maximum number of vertices. for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin(); itr!=geometryDuplicateMap.end(); @@ -1767,11 +1873,13 @@ bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode) } } } +#endif + + // osg::notify(osg::NOTICE)<<"After "<(geode.getDrawable(i)); @@ -1813,6 +1920,97 @@ bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode) geom->getSecondaryColorBinding()!=osg::Geometry::BIND_PER_PRIMITIVE_SET && geom->getFogCoordBinding()!=osg::Geometry::BIND_PER_PRIMITIVE_SET) { + +#if 1 + bool doneCombine = false; + + osg::Geometry::PrimitiveSetList& primitives = geom->getPrimitiveSetList(); + unsigned int lhsNo=0; + unsigned int rhsNo=1; + while(rhsNogetType()==rhs->getType() && + lhs->getMode()==rhs->getMode()) + { + + switch(lhs->getMode()) + { + case(osg::PrimitiveSet::POINTS): + case(osg::PrimitiveSet::LINES): + case(osg::PrimitiveSet::TRIANGLES): + case(osg::PrimitiveSet::QUADS): + combine = true; + break; + } + + } + + if (combine) + { + + switch(lhs->getType()) + { + case(osg::PrimitiveSet::DrawArraysPrimitiveType): + combine = mergePrimitive(*(static_cast(lhs)),*(static_cast(rhs))); + break; + case(osg::PrimitiveSet::DrawArrayLengthsPrimitiveType): + combine = mergePrimitive(*(static_cast(lhs)),*(static_cast(rhs))); + break; + case(osg::PrimitiveSet::DrawElementsUBytePrimitiveType): + combine = mergePrimitive(*(static_cast(lhs)),*(static_cast(rhs))); + break; + case(osg::PrimitiveSet::DrawElementsUShortPrimitiveType): + combine = mergePrimitive(*(static_cast(lhs)),*(static_cast(rhs))); + break; + case(osg::PrimitiveSet::DrawElementsUIntPrimitiveType): + combine = mergePrimitive(*(static_cast(lhs)),*(static_cast(rhs))); + break; + default: + combine = false; + break; + } + } + + if (combine) + { + // make this primitive set as invalid and needing cleaning up. + rhs->setMode(0xffffff); + doneCombine = true; + ++rhsNo; + } + else + { + lhsNo = rhsNo; + ++rhsNo; + } + } + + #if 1 + if (doneCombine) + { + // now need to clean up primitiveset so it no longer contains the rhs combined primitives. + + // first swap with a empty primtiveSet to empty it completely. + osg::Geometry::PrimitiveSetList oldPrimitives; + primitives.swap(oldPrimitives); + + // now add the active primitive sets + for(osg::Geometry::PrimitiveSetList::iterator pitr = oldPrimitives.begin(); + pitr != oldPrimitives.end(); + ++pitr) + { + if ((*pitr)->getMode()!=0xffffff) primitives.push_back(*pitr); + } + } + #endif + +#else + osg::Geometry::PrimitiveSetList& primitives = geom->getPrimitiveSetList(); unsigned int primNo=0; while(primNo+1