From 6d61e554b44ddb278a2901b4121731f3f314062b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 8 May 2008 13:56:28 +0000 Subject: [PATCH] From Paul Martz, "As I discovered prior to the 2.4 release, the FLT export geometry backend was using some old turn-on code, originally written just to enable other development but not intended for actual release. Sadly, my OSG training commitments prevented me from fixing this prior to 2.4. In essence, the FLT exporter was emitting a full set of Mesh records each time it encountered a PrimitiveSet. Attached is a fix. The code now emits the Mesh set up records, then iterates over all PrimitiveSets and emits a Mesh Primitive record per PrimitiveSet. It also loops over PrimitiveSets twice, first writing Face records according to the mode, the writing Mesh records (again according to the mode). The final change included here is support for GL_POINTS as single-vertex Face records. Billboards are still to come." --- .../OpenFlight/FltExportVisitor.cpp | 88 ++++++++--- src/osgPlugins/OpenFlight/FltExportVisitor.h | 8 +- .../OpenFlight/expGeometryRecords.cpp | 142 ++++++------------ 3 files changed, 123 insertions(+), 115 deletions(-) diff --git a/src/osgPlugins/OpenFlight/FltExportVisitor.cpp b/src/osgPlugins/OpenFlight/FltExportVisitor.cpp index 7ad98a469..c449b468f 100644 --- a/src/osgPlugins/OpenFlight/FltExportVisitor.cpp +++ b/src/osgPlugins/OpenFlight/FltExportVisitor.cpp @@ -356,32 +356,80 @@ FltExportVisitor::apply( osg::Geode& node ) ScopedStatePushPop drawableGuard( this, geom->getStateSet() ); - // Write vertex array data out to vertex palette manager - if (!isAllMesh( *geom )) + // 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 pool. + // need to write to the vertex palette. _vertexPalette->add( *geom ); - unsigned int jdx; - for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++) - { - osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx ); - if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) - handleDrawArrays( dynamic_cast( prim ), *geom, node ); - else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) - handleDrawArrayLengths( dynamic_cast( prim ), *geom, node ); - else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || - (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || - (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) - handleDrawElements( dynamic_cast( prim ), *geom, node ); - else + // Iterate over all PrimitiveSets and output Face records. + unsigned int jdx; + for (jdx=0; jdx < geom->getNumPrimitiveSets(); jdx++) { - std::string warning( "fltexp: Unknown PrimitiveSet type." ); - osg::notify( osg::WARN ) << warning << std::endl; - _fltOpt->getWriteResult().warn( warning ); - return; + osg::PrimitiveSet* prim = geom->getPrimitiveSet( jdx ); + if ( isMesh( prim->getMode() ) ) + continue; + + if (prim->getType() == osg::PrimitiveSet::DrawArraysPrimitiveType) + handleDrawArrays( dynamic_cast( prim ), *geom, node ); + else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) + handleDrawArrayLengths( dynamic_cast( prim ), *geom, node ); + else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || + (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || + (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) + handleDrawElements( dynamic_cast( 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( prim ), *geom, node ); + else if (prim->getType() == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) + handleDrawArrayLengths( dynamic_cast( prim ), *geom, node ); + else if ( (prim->getType() == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) || + (prim->getType() == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) || + (prim->getType() == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) ) + handleDrawElements( dynamic_cast( 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. diff --git a/src/osgPlugins/OpenFlight/FltExportVisitor.h b/src/osgPlugins/OpenFlight/FltExportVisitor.h index 120d87e80..747429ba5 100644 --- a/src/osgPlugins/OpenFlight/FltExportVisitor.h +++ b/src/osgPlugins/OpenFlight/FltExportVisitor.h @@ -124,11 +124,11 @@ public: // Geometry records void writeFace( const osg::Geode& geode, const osg::Geometry& geom, GLenum mode ); - void writeMesh( const osg::Geode& geode, const osg::Geometry& geom, GLenum mode ); + void writeMesh( const osg::Geode& geode, const osg::Geometry& geom ); int writeVertexList( int first, unsigned int count ); int writeVertexList( const std::vector& indices, unsigned int count ); void writeMeshPrimitive( const std::vector& indices, GLenum mode ); - void writeLocalVertexPool( const osg::Geometry& geom, GLenum mode ); + void writeLocalVertexPool( const osg::Geometry& geom ); void writeMultitexture( const osg::Geometry& geom ); void writeUVList( int numVerts, const osg::Geometry& geom ); @@ -158,7 +158,9 @@ private: bool isLit( const osg::Geometry& geom ) const; bool isTextured( int unit, const osg::Geometry& geom ) const; - bool isAllMesh( const osg::Geometry& geom ) const; + bool isMesh( const GLenum mode ) const; + bool atLeastOneFace( const osg::Geometry& geom ) const; + bool atLeastOneMesh( const osg::Geometry& geom ) const; osg::ref_ptr< ExportOptions > _fltOpt; diff --git a/src/osgPlugins/OpenFlight/expGeometryRecords.cpp b/src/osgPlugins/OpenFlight/expGeometryRecords.cpp index 438ad9a87..58aed9e32 100644 --- a/src/osgPlugins/OpenFlight/expGeometryRecords.cpp +++ b/src/osgPlugins/OpenFlight/expGeometryRecords.cpp @@ -67,19 +67,40 @@ FltExportVisitor::isTextured( int unit, const osg::Geometry& geom ) const } bool -FltExportVisitor::isAllMesh( const osg::Geometry& geom ) const +FltExportVisitor::isMesh( const GLenum mode ) const { - // Return true if all primitive types will use Mesh records for output. + return( (mode == GL_TRIANGLE_STRIP) || + (mode == GL_TRIANGLE_FAN) || + (mode == GL_QUAD_STRIP) ); +} + +bool +FltExportVisitor::atLeastOneFace( const osg::Geometry& geom ) const +{ + // Return true if at least one PrimitiveSet mode will use a Face record. unsigned int jdx; for (jdx=0; jdx < geom.getNumPrimitiveSets(); jdx++) { const osg::PrimitiveSet* prim = geom.getPrimitiveSet( jdx ); - if( (prim->getMode() != GL_TRIANGLE_STRIP) && - (prim->getMode() != GL_TRIANGLE_FAN) && - (prim->getMode() != GL_QUAD_STRIP) ) - return false; + if( !isMesh( prim->getMode() ) ) + return true; } - return true; + // All PrimitiveSet modes will use Mesh records. + return false; +} +bool +FltExportVisitor::atLeastOneMesh( const osg::Geometry& geom ) const +{ + // Return true if at least one PrimitiveSet mode will use a Mesh record. + unsigned int jdx; + for (jdx=0; jdx < geom.getNumPrimitiveSets(); jdx++) + { + const osg::PrimitiveSet* prim = geom.getPrimitiveSet( jdx ); + if( isMesh( prim->getMode() ) ) + return true; + } + // All PrimitiveSet modes will use Face records. + return false; } void @@ -282,7 +303,7 @@ FltExportVisitor::writeFace( const osg::Geode& geode, const osg::Geometry& geom, void -FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom, GLenum mode ) +FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom ) { enum DrawMode { @@ -354,32 +375,6 @@ FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom, int8 drawType; osg::StateSet const* ss = getCurrentStateSet(); - switch( mode ) - { - case GL_POINTS: - { - std::string warning( "fltexp: GL_POINTS not supported in FLT export." ); - osg::notify( osg::WARN ) << warning << std::endl; - _fltOpt->getWriteResult().warn( warning ); - return; - break; - } - case GL_LINES: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_TRIANGLES: - case GL_QUADS: - { - std::string warning( "fltexp: Wrong mode in Mesh record." ); - osg::notify( osg::WARN ) << warning << std::endl; - _fltOpt->getWriteResult().warn( warning ); - return; - break; - } - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - case GL_QUAD_STRIP: - case GL_POLYGON: { // Default to no facet culling drawType = SOLID_NO_BACKFACE; @@ -394,8 +389,6 @@ FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom, // Note: OpenFlt can't handle FRONT or FRONT_AND_BACK settings, so ignore these(??) } - break; - } } // Determine the material properties for the face @@ -544,7 +537,7 @@ FltExportVisitor::writeMeshPrimitive( const std::vector& indices, } void -FltExportVisitor::writeLocalVertexPool( const osg::Geometry& geom, GLenum mode ) +FltExportVisitor::writeLocalVertexPool( const osg::Geometry& geom ) { // Attribute Mask static const unsigned int HAS_POSITION = 0x80000000u >> 0; @@ -836,11 +829,7 @@ FltExportVisitor::handleDrawArrays( const osg::DrawArrays* da, const osg::Geomet useMesh = true; break; case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_POLYGON: - default: - n = count; + n = 1; break; case GL_LINES: n = 2; @@ -851,40 +840,27 @@ FltExportVisitor::handleDrawArrays( const osg::DrawArrays* da, const osg::Geomet case GL_QUADS: n = 4; break; + case GL_LINE_STRIP: + case GL_LINE_LOOP: + case GL_POLYGON: + default: + n = count; + break; } - // Push and pop subfaces if polygon offset is on. - SubfaceHelper subface( *this, getCurrentStateSet() ); - if (useMesh) { - writeMesh( geode, geom, mode ); - - writeMatrix( geode.getUserData() ); - writeComment( geode ); - writeMultitexture( geom ); - writeLocalVertexPool( geom, mode ); - - writePush(); - std::vector< unsigned int > indices; int jdx; for (jdx=0; jdxbegin(); itr!=dal->end(); itr++ ) @@ -959,8 +928,6 @@ FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, cons indices.push_back( idx ); writeMeshPrimitive( indices, mode ); } - - writePop(); } else { @@ -1016,11 +983,7 @@ FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Ge useMesh = true; break; case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_POLYGON: - default: - n = de->getNumIndices(); + n = 1; break; case GL_LINES: n = 2; @@ -1031,6 +994,12 @@ FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Ge 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. @@ -1038,22 +1007,11 @@ FltExportVisitor::handleDrawElements( const osg::DrawElements* de, const osg::Ge if (useMesh) { - writeMesh( geode, geom, mode ); - - writeMatrix( geode.getUserData() ); - writeComment( geode ); - writeMultitexture( geom ); - writeLocalVertexPool( geom, mode ); - - writePush(); - std::vector< unsigned int > indices; int idx; for (idx=0; idxindex( idx ) ); writeMeshPrimitive( indices, mode ); - - writePop(); } else {