From Aurélien Chatelain, "the smoothing visitor did not handle shared arrays. It may leads to bad geometry arrays when a shared array is involved in the scene.
This submission adds shared array duplication (and moves the SharedArrayOptimizer declaration in MeshOptimizer to make it callable from the SmoothingVisitor)." 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
This commit is contained in:
parent
2870c12b03
commit
a331680cec
@ -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<unsigned int, unsigned int> _deduplicateUvs;
|
||||
}; // SharedArrayOptimizer
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -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<const osg::Array*, unsigned int> 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<const osg::Array*, unsigned int> 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<unsigned int>(channel->referenceCount()) == arrayPointerCounter[channel]) {
|
||||
std::map<const osg::Array*, unsigned int>::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<unsigned int, unsigned int>::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<unsigned int, unsigned int> _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<const osg::Array*, unsigned int> 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<const osg::Array*, unsigned int> 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<unsigned int>(channel->referenceCount()) == arrayPointerCounter[channel])
|
||||
{
|
||||
std::map<const osg::Array*, unsigned int>::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<unsigned int, unsigned int>::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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <stdio.h>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <osgUtil/MeshOptimizers>
|
||||
|
||||
|
||||
using namespace osg;
|
||||
@ -635,6 +636,13 @@ static void smooth_new(osg::Geometry& geom, double creaseAngle)
|
||||
}
|
||||
|
||||
osg::TriangleIndexFunctor<FindSharpEdgesFunctor> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user