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 ); }
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() ); }