Merge pull request #95 from marchelbling/tristripvisitor_index_option

Adds an indexMesh option to disable mesh reindexation
This commit is contained in:
OpenSceneGraph git repository 2016-07-01 18:07:16 +01:00 committed by GitHub
commit 9ae4a4fc27
2 changed files with 164 additions and 133 deletions

View File

@ -37,7 +37,8 @@ class OSGUTIL_EXPORT TriStripVisitor : public BaseOptimizerVisitor
_cacheSize( 16 ),
_minStripSize( 2 ),
_generateFourPointPrimitivesQuads ( false ),
_mergeTriangleStrips( false )
_mergeTriangleStrips( false ),
_indexMesh( true )
{}
/** Convert mesh primitives in Geometry into Tri Strips.
@ -74,6 +75,15 @@ class OSGUTIL_EXPORT TriStripVisitor : public BaseOptimizerVisitor
return _minStripSize;
}
inline void setIndexMesh( bool allow )
{
_indexMesh = allow;
}
inline bool getIndexMesh() const
{
return _indexMesh;
}
void setGenerateFourPointPrimitivesQuads(bool flag) { _generateFourPointPrimitivesQuads = flag; }
bool getGenerateFourPointPrimitivesQuads() const { return _generateFourPointPrimitivesQuads; }
@ -90,6 +100,7 @@ class OSGUTIL_EXPORT TriStripVisitor : public BaseOptimizerVisitor
GeometryList _geometryList;
bool _generateFourPointPrimitivesQuads;
bool _mergeTriangleStrips;
bool _indexMesh;
};
}

View File

@ -187,6 +187,146 @@ protected:
RemapArray& operator = (const RemapArray&) { return *this; }
};
void indexGeometry(osg::Geometry& geom, IndexList& mapping) {
// check for the existence of surface primitives
unsigned int numSurfacePrimitives = 0;
unsigned int numNonSurfacePrimitives = 0;
Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList();
for(Geometry::PrimitiveSetList::iterator itr=primitives.begin();
itr!=primitives.end();
++itr)
{
switch((*itr)->getMode())
{
case(PrimitiveSet::TRIANGLES):
case(PrimitiveSet::TRIANGLE_STRIP):
case(PrimitiveSet::TRIANGLE_FAN):
case(PrimitiveSet::QUADS):
case(PrimitiveSet::QUAD_STRIP):
case(PrimitiveSet::POLYGON):
++numSurfacePrimitives;
break;
default:
++numNonSurfacePrimitives;
break;
}
}
// nothitng to tri strip leave.
if (!numSurfacePrimitives) return;
// compute duplicate vertices
unsigned int numVertices = geom.getVertexArray()->getNumElements();
IndexList vindices(numVertices);
unsigned int i,j;
for(i=0;i<numVertices;++i)
{
vindices[i] = i;
}
VertexAttribComparitor arrayComparitor(geom);
std::sort(vindices.begin(),vindices.end(),arrayComparitor);
unsigned int lastUnique = 0;
unsigned int numUnique = 1;
unsigned int numDuplicate = 0;
for(i=1;i<numVertices;++i)
{
if (arrayComparitor.compare(vindices[lastUnique],vindices[i])==0)
{
++numDuplicate;
}
else
{
lastUnique = i;
++numUnique;
}
}
IndexList remapDuplicatesToOrignals(numVertices);
lastUnique = 0;
for(i=1;i<numVertices;++i)
{
if (arrayComparitor.compare(vindices[lastUnique],vindices[i])!=0)
{
// found a new vertex entry, so previous run of duplicates needs
// to be put together.
unsigned int min_index = vindices[lastUnique];
for(j=lastUnique+1;j<i;++j)
{
min_index = osg::minimum(min_index,vindices[j]);
}
for(j=lastUnique;j<i;++j)
{
remapDuplicatesToOrignals[vindices[j]]=min_index;
}
lastUnique = i;
}
}
unsigned int min_index = vindices[lastUnique];
for(j=lastUnique+1;j<i;++j)
{
min_index = osg::minimum(min_index,vindices[j]);
}
for(j=lastUnique;j<i;++j)
{
remapDuplicatesToOrignals[vindices[j]]=min_index;
}
// copy the arrays.
IndexList finalMapping(numVertices);
IndexList copyMapping;
copyMapping.reserve(numUnique);
unsigned int currentIndex=0;
for(i=0;i<numVertices;++i)
{
if (remapDuplicatesToOrignals[i]==i)
{
finalMapping[i] = currentIndex;
copyMapping.push_back(i);
currentIndex++;
}
}
for(i=0;i<numVertices;++i)
{
if (remapDuplicatesToOrignals[i]!=i)
{
finalMapping[i] = finalMapping[remapDuplicatesToOrignals[i]];
}
}
float minimum_ratio_of_indices_to_unique_vertices = 1;
unsigned int nbPrimitiveIndices = 0;
for(unsigned int k = 0 ; k < geom.getNumPrimitiveSets() ; ++ k) {
osg::PrimitiveSet* primitive = geom.getPrimitiveSet(k);
if(primitive) {
nbPrimitiveIndices += primitive->getNumIndices();
}
}
float ratio_of_indices_to_unique_vertices = ((float)nbPrimitiveIndices/(float)numUnique);
if(!finalMapping.empty() &&
ratio_of_indices_to_unique_vertices >= minimum_ratio_of_indices_to_unique_vertices) {
OSG_INFO << "TriStripVisitor::stripify(Geometry&): Number of indices" << nbPrimitiveIndices
<< " numUnique" << numUnique << std::endl;
OSG_INFO << "TriStripVisitor::stripify(Geometry&): ratio indices/numUnique"
<< ratio_of_indices_to_unique_vertices << std::endl;
// remap any shared vertex attributes
RemapArray ra(copyMapping);
arrayComparitor.accept(ra);
finalMapping.swap(mapping);
}
}
struct MyTriangleOperator
{
@ -227,129 +367,20 @@ void TriStripVisitor::stripify(Geometry& geom)
// no point tri stripping if we don't have enough vertices.
if (!geom.getVertexArray() || geom.getVertexArray()->getNumElements()<3) return;
// check for the existence of surface primitives
unsigned int numSurfacePrimitives = 0;
unsigned int numNonSurfacePrimitives = 0;
Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList();
for(Geometry::PrimitiveSetList::iterator itr=primitives.begin();
itr!=primitives.end();
++itr)
{
switch((*itr)->getMode())
{
case(PrimitiveSet::TRIANGLES):
case(PrimitiveSet::TRIANGLE_STRIP):
case(PrimitiveSet::TRIANGLE_FAN):
case(PrimitiveSet::QUADS):
case(PrimitiveSet::QUAD_STRIP):
case(PrimitiveSet::POLYGON):
++numSurfacePrimitives;
break;
default:
++numNonSurfacePrimitives;
break;
IndexList mapping;
if(_indexMesh) {
indexGeometry(geom, mapping);
if(mapping.empty()) {
return;
}
}
// nothitng to tri strip leave.
if (!numSurfacePrimitives) return;
// compute duplicate vertices
unsigned int numVertices = geom.getVertexArray()->getNumElements();
IndexList vindices(numVertices);
unsigned int i,j;
for(i=0;i<numVertices;++i)
{
vindices[i] = i;
}
VertexAttribComparitor arrayComparitor(geom);
std::sort(vindices.begin(), vindices.end(), arrayComparitor);
unsigned int lastUnique = 0;
unsigned int numUnique = 1;
unsigned int numDuplicate = 0;
for(i=1;i<numVertices;++i)
{
if (arrayComparitor.compare(vindices[lastUnique], vindices[i])==0)
{
//std::cout<<" found duplicate "<<indices[lastUnique]<<" and "<<indices[i]<<std::endl;
++numDuplicate;
}
else
{
//std::cout<<" unique "<<indices[i]<<std::endl;
lastUnique = i;
++numUnique;
}
}
// std::cout<<" Number of duplicates "<<numDuplicate<<std::endl;
// std::cout<<" Number of unique "<<numUnique<<std::endl;
// std::cout<<" Total number of vertices required "<<numUnique<<" vs original "<<numVertices<<std::endl;
// std::cout<<" % size "<<(float)numUnique/(float)numVertices*100.0f<<std::endl;
IndexList remapDuplicatesToOrignals(numVertices);
lastUnique = 0;
for(i=1;i<numVertices;++i)
{
if (arrayComparitor.compare(vindices[lastUnique], vindices[i])!=0)
{
// found a new vertex entry, so previous run of duplicates needs
// to be put together.
unsigned int min_index = vindices[lastUnique];
for(j=lastUnique+1;j<i;++j)
{
min_index = osg::minimum(min_index, vindices[j]);
}
for(j=lastUnique;j<i;++j)
{
remapDuplicatesToOrignals[vindices[j]]=min_index;
}
lastUnique = i;
}
}
unsigned int min_index = vindices[lastUnique];
for(j=lastUnique+1;j<i;++j)
{
min_index = osg::minimum(min_index, vindices[j]);
}
for(j=lastUnique;j<i;++j)
{
remapDuplicatesToOrignals[vindices[j]]=min_index;
}
// copy the arrays.
IndexList finalMapping(numVertices);
IndexList copyMapping;
copyMapping.reserve(numUnique);
unsigned int currentIndex=0;
for(i=0;i<numVertices;++i)
{
if (remapDuplicatesToOrignals[i]==i)
{
finalMapping[i] = currentIndex;
copyMapping.push_back(i);
currentIndex++;
}
}
for(i=0;i<numVertices;++i)
{
if (remapDuplicatesToOrignals[i]!=i)
{
finalMapping[i] = finalMapping[remapDuplicatesToOrignals[i]];
}
}
MyTriangleIndexFunctor taf;
taf._remapIndices.swap(finalMapping);
if(!mapping.empty()) {
taf._remapIndices.swap(mapping);
}
Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList();
Geometry::PrimitiveSetList new_primitives;
new_primitives.reserve(primitives.size());
@ -370,18 +401,11 @@ void TriStripVisitor::stripify(Geometry& geom)
default:
new_primitives.push_back(*itr);
break;
}
}
float minimum_ratio_of_indices_to_unique_vertices = 1;
float ratio_of_indices_to_unique_vertices = ((float)taf._in_indices.size()/(float)numUnique);
OSG_INFO<<"TriStripVisitor::stripify(Geometry&): Number of indices"<<taf._in_indices.size()<<" numUnique"<< numUnique << std::endl;
OSG_INFO<<"TriStripVisitor::stripify(Geometry&): ratio indices/numUnique"<< ratio_of_indices_to_unique_vertices << std::endl;
// only tri strip if there is point in doing so.
if (!taf._in_indices.empty() && ratio_of_indices_to_unique_vertices>=minimum_ratio_of_indices_to_unique_vertices)
if (!taf._in_indices.empty())
{
OSG_INFO<<"TriStripVisitor::stripify(Geometry&): doing tri strip"<< std::endl;
@ -393,13 +417,9 @@ void TriStripVisitor::stripify(Geometry& geom)
if (*itr>in_numVertices) in_numVertices=*itr;
}
// the largest indice is in_numVertices, but indices start at 0
// so increment to give to the corrent number of verticies.
// so increment to give to the corrent number of vertices.
++in_numVertices;
// remap any shared vertex attributes
RemapArray ra(copyMapping);
arrayComparitor.accept(ra);
triangle_stripper::tri_stripper stripifier(taf._in_indices);
stripifier.SetCacheSize(_cacheSize);
stripifier.SetMinStripSize(_minStripSize);
@ -450,7 +470,7 @@ void TriStripVisitor::stripify(Geometry& geom)
pitr = qitr->second;
unsigned int min_pos = 0;
for(i=1;i<4;++i)
for(unsigned int i = 1 ; i < 4 ; ++ i)
{
if (pitr->Indices[min_pos]>pitr->Indices[i])
min_pos = i;