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."
This commit is contained in:
Robert Osfield
2008-05-08 13:56:28 +00:00
parent 0df8d414f4
commit 6d61e554b4
3 changed files with 123 additions and 115 deletions

View File

@@ -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<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
// 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<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.

View File

@@ -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<unsigned int>& indices, unsigned int count );
void writeMeshPrimitive( const std::vector<unsigned int>& 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;

View File

@@ -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<unsigned int>& 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; jdx<count; jdx++)
indices.push_back( first+jdx );
writeMeshPrimitive( indices, mode );
writePop();
}
else
{
const unsigned int max( first+count );
while ((unsigned int)( first+n ) <= max)
{
// 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() );
@@ -919,10 +895,7 @@ FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, cons
useMesh = true;
break;
case GL_POINTS:
case GL_LINE_STRIP:
case GL_LINE_LOOP:
case GL_POLYGON:
default:
n = 1;
break;
case GL_LINES:
n = 2;
@@ -933,6 +906,11 @@ FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, cons
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.
@@ -940,15 +918,6 @@ FltExportVisitor::handleDrawArrayLengths( const osg::DrawArrayLengths* dal, cons
if (useMesh)
{
writeMesh( geode, geom, mode );
writeMatrix( geode.getUserData() );
writeComment( geode );
writeMultitexture( geom );
writeLocalVertexPool( geom, mode );
writePush();
int idx( 0 );
for( osg::DrawArrayLengths::const_iterator itr=dal->begin();
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; idx<n; idx++)
indices.push_back( de->index( idx ) );
writeMeshPrimitive( indices, mode );
writePop();
}
else
{