From a331680cec2318163a3d20b40223c09474fcc7b9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 24 Dec 2014 10:55:49 +0000 Subject: [PATCH] =?UTF-8?q?From=20Aur=C3=A9lien=20Chatelain,=20"the=20smoo?= =?UTF-8?q?thing=20visitor=20did=20not=20handle=20shared=20arrays.=20It=20?= =?UTF-8?q?may=20leads=20to=20bad=20geometry=20arrays=20when=20a=20shared?= =?UTF-8?q?=20array=20is=20involved=20in=20the=20scene.=20This=20submissio?= =?UTF-8?q?n=20adds=20shared=20array=20duplication=20(and=20moves=20the=20?= =?UTF-8?q?SharedArrayOptimizer=20declaration=20in=20MeshOptimizer=20to=20?= =?UTF-8?q?make=20it=20callable=20from=20the=20SmoothingVisitor)."?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submitted by Marc Helbling. Edited by Robet Osfield to retain the usual OSG coding style. git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14639 16af8721-9629-0410-8352-f15c8da7e697 --- include/osgUtil/MeshOptimizers | 10 +++ src/osgUtil/MeshOptimizers.cpp | 111 ++++++++++++++++--------------- src/osgUtil/SmoothingVisitor.cpp | 10 +++ 3 files changed, 77 insertions(+), 54 deletions(-) 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); } }