diff --git a/include/osgUtil/MeshOptimizers b/include/osgUtil/MeshOptimizers index c35bcfc6c..c1402661c 100644 --- a/include/osgUtil/MeshOptimizers +++ b/include/osgUtil/MeshOptimizers @@ -111,5 +111,15 @@ public: void optimizeOrder(); void optimizeOrder(osg::Geometry& geom); }; + +class OSGUTIL_EXPORT SharedArrayOptimizer +{ +public: + void findDuplicatedUVs(const osg::Geometry& geometry); + void deduplicateUVs(osg::Geometry& geometry); +protected: + std::map _deduplicateUvs; +}; // SharedArrayOptimizer + } #endif diff --git a/src/osgUtil/MeshOptimizers.cpp b/src/osgUtil/MeshOptimizers.cpp index 4fe84feb6..e424e0227 100644 --- a/src/osgUtil/MeshOptimizers.cpp +++ b/src/osgUtil/MeshOptimizers.cpp @@ -99,60 +99,6 @@ struct GeometryArrayGatherer ArrayList _arrayList; }; -class SharedArrayOptimizer { -public: - void findDuplicatedUVs(const osg::Geometry& geometry) - { - _deduplicateUvs.clear(); - - // look for all channels that are shared only *within* the geometry - std::map arrayPointerCounter; - - for(unsigned int id = 0 ; id < geometry.getNumTexCoordArrays() ; ++ id) { - const osg::Array* channel = geometry.getTexCoordArray(id); - if(channel && channel->getNumElements()) { - if(arrayPointerCounter.find(channel) == arrayPointerCounter.end()) { - arrayPointerCounter[channel] = 1; - } - else { - arrayPointerCounter[channel] += 1; - } - } - } - - std::map references; - - for(unsigned int id = 0 ; id != geometry.getNumTexCoordArrays() ; ++ id) { - const osg::Array* channel = geometry.getTexCoordArray(id); - // test if array is shared outside the geometry - if(channel && static_cast(channel->referenceCount()) == arrayPointerCounter[channel]) { - std::map::const_iterator reference = references.find(channel); - if(reference == references.end()) { - references[channel] = id; - } - else { - _deduplicateUvs[id] = reference->second; - } - } - } - } - - void deduplicateUVs(osg::Geometry& geometry) - { - for(std::map::const_iterator it_duplicate = _deduplicateUvs.begin() ; - it_duplicate != _deduplicateUvs.end() ; ++ it_duplicate) { - osg::Array* original = geometry.getTexCoordArray(it_duplicate->second); - geometry.setTexCoordArray(it_duplicate->first, - original, - (original ? original->getBinding() : osg::Array::BIND_UNDEFINED)); - } - } - -protected: - std::map _deduplicateUvs; -}; - - // Compare vertices in a mesh using all their attributes. The vertices // are identified by their index. Extracted from TriStripVisitor.cpp struct VertexAttribComparitor : public GeometryArrayGatherer @@ -1244,4 +1190,61 @@ void VertexAccessOrderVisitor::optimizeOrder(Geometry& geom) geom.dirtyDisplayList(); } + +void SharedArrayOptimizer::findDuplicatedUVs(const osg::Geometry& geometry) +{ + _deduplicateUvs.clear(); + + // look for all channels that are shared only *within* the geometry + std::map arrayPointerCounter; + + for(unsigned int id = 0 ; id < geometry.getNumTexCoordArrays() ; ++ id) + { + const osg::Array* channel = geometry.getTexCoordArray(id); + if(channel && channel->getNumElements()) + { + if(arrayPointerCounter.find(channel) == arrayPointerCounter.end()) + { + arrayPointerCounter[channel] = 1; + } + else + { + arrayPointerCounter[channel] += 1; + } + } + } + + std::map references; + + for(unsigned int id = 0 ; id != geometry.getNumTexCoordArrays() ; ++ id) + { + const osg::Array* channel = geometry.getTexCoordArray(id); + // test if array is shared outside the geometry + if(channel && static_cast(channel->referenceCount()) == arrayPointerCounter[channel]) + { + std::map::const_iterator reference = references.find(channel); + if(reference == references.end()) + { + references[channel] = id; + } + else + { + _deduplicateUvs[id] = reference->second; + } + } + } +} + +void SharedArrayOptimizer::deduplicateUVs(osg::Geometry& geometry) +{ + for(std::map::const_iterator it_duplicate = _deduplicateUvs.begin() ; + it_duplicate != _deduplicateUvs.end() ; ++ it_duplicate) + { + osg::Array* original = geometry.getTexCoordArray(it_duplicate->second); + geometry.setTexCoordArray(it_duplicate->first, + original, + (original ? original->getBinding() : osg::Array::BIND_UNDEFINED)); + } +} + } diff --git a/src/osgUtil/SmoothingVisitor.cpp b/src/osgUtil/SmoothingVisitor.cpp index 31f443aad..cf0693bfc 100644 --- a/src/osgUtil/SmoothingVisitor.cpp +++ b/src/osgUtil/SmoothingVisitor.cpp @@ -19,6 +19,7 @@ #include #include #include +#include using namespace osg; @@ -635,6 +636,13 @@ static void smooth_new(osg::Geometry& geom, double creaseAngle) } osg::TriangleIndexFunctor fsef; + + osgUtil::SharedArrayOptimizer sharedArrayOptimizer; + sharedArrayOptimizer.findDuplicatedUVs(geom); + + // Duplicate shared arrays to avoid index errors during duplication + if (geom.containsSharedArrays()) geom.duplicateSharedArrays(); + if (fsef.set(&geom, creaseAngle)) { // look for normals that deviate too far @@ -660,6 +668,8 @@ static void smooth_new(osg::Geometry& geom, double creaseAngle) } } + + sharedArrayOptimizer.deduplicateUVs(geom); } }