void FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Geometry& geom, const osg::Geode& geode ) { GLenum mode = de->getMode(); int n( 0 ); bool useMesh( false ); switch( mode ) { case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_QUAD_STRIP: n = de->getNumIndices(); useMesh = true; break; case GL_POINTS: n = 1; break; case GL_LINES: n = 2; break; case GL_TRIANGLES: n = 3; break; case GL_QUADS: n = 4; break; case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_POLYGON: default: n = de->getNumIndices(); break; } // Push and pop subfaces if polygon offset is on. SubfaceHelper subface( *this, getCurrentStateSet() ); if (useMesh) { std::vector< unsigned int > indices; int idx; for (idx=0; idx<n; idx++) indices.push_back( de->index( idx ) ); writeMeshPrimitive( indices, mode ); } else { unsigned int first( 0 ); while (first+n <= de->getNumIndices()) { // Need: // * Geode for record name (but also need to handle // multi Geometry objects and multi PrimitiveSet objects; // all Face records can't have the same name). // * Mode writeFace( geode, geom, mode ); writeMatrix( geode.getUserData() ); writeComment( geode ); writeMultitexture( geom ); writePush(); // Write vertex list records. std::vector<unsigned int> indices; int idx; for(idx=0; idx<n; idx++) indices.push_back( de->index( first+idx ) ); int numVerts = writeVertexList( indices, n ); first += n; writeUVList( numVerts, geom ); writePop(); } } }
void FltExportVisitor::handleDrawArrays( const osg::DrawArrays* da, const osg::Geometry& geom, const osg::Geode& geode ) { GLint first = da->getFirst(); GLsizei count = da->getCount(); GLenum mode = da->getMode(); int n( 0 ); bool useMesh( false ); switch( mode ) { case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_QUAD_STRIP: useMesh = true; break; case GL_POINTS: n = 1; break; case GL_LINES: n = 2; break; case GL_TRIANGLES: n = 3; break; case GL_QUADS: n = 4; break; case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_POLYGON: default: n = count; break; } if (useMesh) { std::vector< unsigned int > indices; int jdx; for (jdx=0; jdx<count; jdx++) indices.push_back( first+jdx ); writeMeshPrimitive( indices, mode ); } else { const unsigned int max( first+count ); while ((unsigned int)( first+n ) <= max) { writeFace( geode, geom, mode ); writeMatrix( geode.getUserData() ); writeComment( geode ); writeMultitexture( geom ); writePush(); // Write vertex list records. int numVerts = writeVertexList( first, n ); first += n; writeUVList( numVerts, geom ); writePop(); } } }
void FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, const osg::Geometry& geom, const osg::Geode& geode ) { GLint first = dal->getFirst(); GLenum mode = dal->getMode(); int n( 0 ); bool useMesh( false ); switch( mode ) { case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_QUAD_STRIP: useMesh = true; break; case GL_POINTS: n = 1; break; case GL_LINES: n = 2; break; case GL_TRIANGLES: n = 3; break; case GL_QUADS: n = 4; break; case GL_LINE_STRIP: case GL_LINE_LOOP: case GL_POLYGON: default: break; } // Push and pop subfaces if polygon offset is on. SubfaceHelper subface( *this, getCurrentStateSet() ); if (useMesh) { int idx( 0 ); for( osg::DrawArrayLengths::const_iterator itr=dal->begin(); itr!=dal->end(); itr++ ) { std::vector< unsigned int > indices; int jdx; for (jdx=0; jdx<(*itr); idx++, jdx++) indices.push_back( idx ); writeMeshPrimitive( indices, mode ); } } else { // Hm. You wouldn't usually use DrawArrayLengths for non-strip/fan prims... for( osg::DrawArrayLengths::const_iterator itr=dal->begin(); itr!=dal->end(); itr++ ) { while (first+n <= *itr) { writeFace( geode, geom, mode ); writeMatrix( geode.getUserData() ); writeComment( geode ); writeMultitexture( geom ); writePush(); // Write vertex list records. int numVerts; if (n == 0) { numVerts = writeVertexList( first, *itr ); first += *itr; } else { numVerts = writeVertexList( first, n ); first += n; } writeUVList( numVerts, geom ); writePop(); } first += *itr; } } }
// Billboards also go through this code. The Geode is passed // to writeFace and writeMesh. If those methods successfully cast // the Geode to a Billboard, then they set the template mode // bit accordingly. void FltExportVisitor::apply( osg::Geode& node ) { _firstNode = false; ScopedStatePushPop guard( this, node.getStateSet() ); unsigned int idx; for (idx=0; idx<node.getNumDrawables(); idx++) { osg::Geometry* geom = node.getDrawable( idx )->asGeometry(); if (!geom) { std::string warning( "fltexp: Non-Geometry Drawable encountered. Ignoring." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); continue; } ScopedStatePushPop drawableGuard( this, geom->getStateSet() ); // Push and pop subfaces if polygon offset is on. SubfaceHelper subface( *this, getCurrentStateSet() ); if (atLeastOneFace( *geom )) { // If at least one record will be a Face record, then we // need to write to the vertex palette. _vertexPalette->add( *geom ); // Iterate over all PrimitiveSets and output Face records. unsigned int jdx; for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++) { osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx ); if ( isMesh( prim->getMode() ) ) continue; if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) handleDrawArrays( dynamic_cast<osg::DrawArrays*>( prim ), *geom, node ); else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) handleDrawArrayLengths( dynamic_cast<osg::DrawArrayLengths*>( prim ), *geom, node ); else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) handleDrawElements( dynamic_cast<osg::DrawElements*>( prim ), *geom, node ); else { std::string warning( "fltexp: Unknown PrimitiveSet type." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } } } if (atLeastOneMesh( *geom )) { // If at least one Mesh record, write out preamble mesh records // followed by a Mesh Primitive record per PrimitiveSet. writeMesh( node, *geom ); writeMatrix( node.getUserData() ); writeComment( node ); writeMultitexture( *geom ); writeLocalVertexPool( *geom ); writePush(); unsigned int jdx; for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++) { osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx ); if ( !isMesh( prim->getMode() ) ) continue; if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) handleDrawArrays( dynamic_cast<osg::DrawArrays*>( prim ), *geom, node ); else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) handleDrawArrayLengths( dynamic_cast<osg::DrawArrayLengths*>( prim ), *geom, node ); else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) handleDrawElements( dynamic_cast<osg::DrawElements*>( prim ), *geom, node ); else { std::string warning( "fltexp: Unknown PrimitiveSet type." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } } writePop(); } } // Would traverse here if this node could have children. // traverse( (osg::Node&)node ); }