|
osgEarth 2.1.1
|
Static Public Member Functions | |
| static void | run (osg::Geometry &geom) |
| static void | run (osg::Geode &geode) |
Consolidates all the like-moded primitive sets in a geometry.
This utility will attempt to extract all triangular primitives from a geometry and regroup them into a smaller number of primitive sets. For example, if you have a geometry with triangle strips, fans, and triangles, it will combines them into one a minimal number of primitive sets containing GL_TRIANGLES.
Limitations:
Definition at line 43 of file MeshConsolidator.
| void MeshConsolidator::run | ( | osg::Geometry & | geom | ) | [static] |
Definition at line 114 of file MeshConsolidator.cpp.
{
if ( !canOptimize(geom) )
return;
osg::Geometry::PrimitiveSetList& primSets = geom.getPrimitiveSetList();
osg::Geometry::PrimitiveSetList triSets, nonTriSets;
for( osg::Geometry::PrimitiveSetList::iterator i = primSets.begin(); i != primSets.end(); ++i )
{
osg::PrimitiveSet* pset = i->get();
switch( pset->getMode() )
{
case osg::PrimitiveSet::TRIANGLES:
case osg::PrimitiveSet::TRIANGLE_STRIP:
case osg::PrimitiveSet::TRIANGLE_FAN:
case osg::PrimitiveSet::QUADS:
case osg::PrimitiveSet::QUAD_STRIP:
case osg::PrimitiveSet::POLYGON:
triSets.push_back( pset );
break;
default:
nonTriSets.push_back( pset );
}
}
if ( triSets.size() > 0 )
{
osg::Array* vertexArray = geom.getVertexArray();
unsigned numVerts = vertexArray->getNumElements();
osg::Geometry::PrimitiveSetList newPrimSets;
if ( numVerts < 0x100 )
{
osg::TriangleIndexFunctor< Collector<osg::DrawElementsUByte> > collector;
collector._newPrimSets = &newPrimSets;
collector._maxSize = 0xFF;
geom.accept( collector );
}
else if ( numVerts < 0x10000 )
{
osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector;
collector._newPrimSets = &newPrimSets;
collector._maxSize = 0xFFFF;
geom.accept( collector );
}
else
{
osg::TriangleIndexFunctor< Collector<osg::DrawElementsUInt> > collector;
collector._newPrimSets = &newPrimSets;
collector._maxSize = 0xFFFFFFFF;
geom.accept( collector );
}
for( osg::Geometry::PrimitiveSetList::iterator i = newPrimSets.begin(); i != newPrimSets.end(); ++i )
nonTriSets.push_back( i->get() );
}
geom.setPrimitiveSetList( nonTriSets );
}
Here is the call graph for this function:
Here is the caller graph for this function:| void MeshConsolidator::run | ( | osg::Geode & | geode | ) | [static] |
Definition at line 177 of file MeshConsolidator.cpp.
{
unsigned numVerts = 0;
unsigned numColors = 0;
unsigned numNormals = 0;
unsigned numTexCoordArrays = 0;
unsigned numVertAttribArrays = 0;
std::vector<unsigned> texCoordArrayUnits;
osg::Geometry::AttributeBinding newColorsBinding;
osg::Geometry::AttributeBinding newNormalsBinding;
// first, triangulate all the geometries and count all the components:
for( unsigned i=0; i<geode.getNumDrawables(); ++i )
{
osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
if ( geom )
{
if ( !canOptimize(*geom) )
continue;
// optimize it into triangles first:
run( *geom );
osg::Array* verts = geom->getVertexArray();
if ( verts )
numVerts += verts->getNumElements();
osg::Array* colors = geom->getColorArray();
if ( colors )
numColors += colors->getNumElements();
osg::Array* normals = geom->getNormalArray();
if ( normals )
numNormals += normals->getNumElements();
// NOTE!! tex/attrib array counts much already be equal.
if ( texCoordArrayUnits.size() == 0 )
{
for( unsigned u=0; u<32; ++u ) {
if ( geom->getTexCoordArray(u) != 0L )
texCoordArrayUnits.push_back( u );
}
}
numVertAttribArrays += geom->getNumVertexAttribArrays();
}
}
// bail if there are unsupported items in there.
if (geode.getNumDrawables() < 2 ||
//numTexCoordArrays > 0 ||
numVertAttribArrays > 0 )
{
return;
}
osg::Vec3Array* newVerts = new osg::Vec3Array();
newVerts->reserve( numVerts );
osg::Vec4Array* newColors =0L;
if ( numColors > 0 )
{
newColors = new osg::Vec4Array();
newColors->reserve( numVerts );
newColorsBinding = osg::Geometry::BIND_PER_VERTEX;
//newColors->reserve( numColors==numVerts? numColors : 1 );
//newColorsBinding = numColors==numVerts? osg::Geometry::BIND_PER_VERTEX : osg::Geometry::BIND_OVERALL;
}
osg::Vec3Array* newNormals =0L;
if ( numNormals > 0 )
{
newNormals = new osg::Vec3Array();
newNormals->reserve( numVerts );
newNormalsBinding = osg::Geometry::BIND_PER_VERTEX;
//newNormals->reserve( numNormals==numVerts? numNormals : 1 );
//newNormalsBinding = numNormals==numVerts? osg::Geometry::BIND_PER_VERTEX : osg::Geometry::BIND_OVERALL;
}
std::vector<osg::Vec2Array*> newTexCoordsArrays;
for( unsigned i=0; i<texCoordArrayUnits.size(); ++i )
{
osg::Vec2Array* newTexCoords = new osg::Vec2Array();
newTexCoords->reserve( numVerts );
newTexCoordsArrays.push_back( newTexCoords );
}
unsigned offset = 0;
osg::Geometry::PrimitiveSetList newPrimSets;
std::vector<osg::ref_ptr<osg::Geometry> > nonOptimizedGeoms;
osg::StateSet* unifiedStateSet = 0L;
for( unsigned i=0; i<geode.getNumDrawables(); ++i )
{
osg::Geometry* geom = geode.getDrawable(i)->asGeometry();
if ( geom )
{
if ( !canOptimize(*geom) )
{
nonOptimizedGeoms.push_back(geom);
continue;
}
// merge in the stateset:
if ( unifiedStateSet == 0L )
unifiedStateSet = geom->getStateSet();
else if ( geom->getStateSet() )
unifiedStateSet->merge( *geom->getStateSet() );
// copy over the verts:
osg::Vec3Array* geomVerts = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() );
if ( geomVerts )
{
std::copy( geomVerts->begin(), geomVerts->end(), std::back_inserter(*newVerts) );
if ( newColors )
{
osg::Vec4Array* colors = dynamic_cast<osg::Vec4Array*>( geom->getColorArray() );
if ( colors )
{
if ( newColorsBinding == osg::Geometry::BIND_PER_VERTEX )
{
std::copy( colors->begin(), colors->end(), std::back_inserter(*newColors) );
}
else if ( i == 0 ) // overall
{
newColors->push_back( (*colors)[0] );
}
}
}
if ( newNormals )
{
osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>( geom->getNormalArray() );
if ( normals )
{
if ( newNormalsBinding == osg::Geometry::BIND_PER_VERTEX )
{
std::copy( normals->begin(), normals->end(), std::back_inserter(*newNormals) );
}
else if ( i == 0 ) // overall
{
newNormals->push_back( (*normals)[0] );
}
}
}
if ( newTexCoordsArrays.size() > 0 )
{
for( unsigned a=0; a<texCoordArrayUnits.size(); ++a )
{
unsigned unit = texCoordArrayUnits[a];
osg::Vec2Array* texCoords = dynamic_cast<osg::Vec2Array*>( geom->getTexCoordArray(unit) );
if ( texCoords )
{
osg::Vec2Array* newTexCoords = newTexCoordsArrays[a];
std::copy( texCoords->begin(), texCoords->end(), std::back_inserter(*newTexCoords) );
}
}
}
for( unsigned j=0; j < geom->getNumPrimitiveSets(); ++j )
{
osg::PrimitiveSet* pset = geom->getPrimitiveSet(j);
osg::PrimitiveSet* newpset = 0L;
if ( dynamic_cast<osg::DrawElementsUByte*>(pset) )
newpset = remake( static_cast<osg::DrawElementsUByte*>(pset), numVerts, offset );
else if ( dynamic_cast<osg::DrawElementsUShort*>(pset) )
newpset = remake( static_cast<osg::DrawElementsUShort*>(pset), numVerts, offset );
else if ( dynamic_cast<osg::DrawElementsUInt*>(pset) )
newpset = remake( static_cast<osg::DrawElementsUInt*>(pset), numVerts, offset );
else if ( dynamic_cast<osg::DrawArrays*>(pset) )
newpset = new osg::DrawArrays( pset->getMode(), offset, geomVerts->size() );
if ( newpset )
newPrimSets.push_back( newpset );
}
offset += geomVerts->size();
}
}
}
// assemble the new geometry.
osg::Geometry* newGeom = new osg::Geometry();
newGeom->setVertexArray( newVerts );
if ( newColors )
{
newGeom->setColorArray( newColors );
newGeom->setColorBinding( newColorsBinding );
}
if ( newNormals )
{
newGeom->setNormalArray( newNormals );
newGeom->setNormalBinding( newNormalsBinding );
}
if ( newTexCoordsArrays.size() > 0 )
{
for( unsigned a=0; a<texCoordArrayUnits.size(); ++a )
{
unsigned unit = texCoordArrayUnits[a];
newGeom->setTexCoordArray( unit, newTexCoordsArrays[a] );
}
}
newGeom->setPrimitiveSetList( newPrimSets );
newGeom->setStateSet( unifiedStateSet );
// replace the geode's drawables
geode.removeDrawables( 0, geode.getNumDrawables() );
geode.addDrawable( newGeom );
for( std::vector<osg::ref_ptr<osg::Geometry> >::iterator i = nonOptimizedGeoms.begin(); i != nonOptimizedGeoms.end(); ++i )
geode.addDrawable( i->get() );
}
Here is the call graph for this function:
1.7.3