From Guy Volckaert, "Changes to the openflight plugin to support replacing double sided polygons by 2 opposite facing polygons. This is sometimes required to resolved lighting and intersection issues. A new import option was was added to activate this feature called "replaceDoubleSidedPolys".

This commit is contained in:
Robert Osfield
2011-01-14 14:30:19 +00:00
parent fac9992bca
commit 2b3bba8587
4 changed files with 136 additions and 2 deletions

View File

@@ -26,6 +26,7 @@ Document::Document() :
_replaceClampWithClampToEdge(false),
_preserveFace(false),
_preserveObject(false),
_replaceDoubleSidedPolys(false),
_defaultDOFAnimationState(false),
_useTextureAlphaForTransparancyBinning(true),
_useBillboardCenter(false),

View File

@@ -183,6 +183,8 @@ class Document
bool getPreserveFace() const { return _preserveFace; }
void setPreserveObject(bool flag) { _preserveObject = flag; }
bool getPreserveObject() const { return _preserveObject; }
void setReplaceDoubleSidedPolys(bool flag) { _replaceDoubleSidedPolys = flag; }
bool getReplaceDoubleSidedPolys() const { return _replaceDoubleSidedPolys; }
void setDefaultDOFAnimationState(bool state) { _defaultDOFAnimationState = state; }
bool getDefaultDOFAnimationState() const { return _defaultDOFAnimationState; }
void setUseTextureAlphaForTransparancyBinning(bool flag) { _useTextureAlphaForTransparancyBinning=flag; }
@@ -207,6 +209,7 @@ class Document
bool _replaceClampWithClampToEdge;
bool _preserveFace;
bool _preserveObject;
bool _replaceDoubleSidedPolys;
bool _defaultDOFAnimationState;
bool _useTextureAlphaForTransparancyBinning;
bool _useBillboardCenter;

View File

@@ -29,8 +29,108 @@
#include "Document.h"
#include "RecordInputStream.h"
#include <algorithm>
namespace flt {
template<class ARRAY>
void reverseWindingOrder( ARRAY* data, GLenum mode, GLint first, GLint last )
{
switch( mode )
{
case osg::PrimitiveSet::TRIANGLES:
case osg::PrimitiveSet::QUADS:
case osg::PrimitiveSet::POLYGON:
// reverse all the vertices.
std::reverse(data->begin()+first, data->begin()+last);
break;
case osg::PrimitiveSet::TRIANGLE_STRIP:
case osg::PrimitiveSet::QUAD_STRIP:
// reverse only the shared edges.
for( GLint i = first; i < last-1; i+=2 )
{
std::swap( (*data)[i], (*data)[i+1] );
}
break;
case osg::PrimitiveSet::TRIANGLE_FAN:
// reverse all vertices except the first vertex.
std::reverse(data->begin()+first+1, data->begin()+last);
break;
}
}
void addDrawableAndReverseWindingOrder( osg::Geode* geode )
{
// Replace double sided polygons by duplicating the drawables and inverting the normals.
std::vector<osg::Geometry*> new_drawables;
for (size_t i=0; i<geode->getNumDrawables(); ++i)
{
const osg::Geometry* geometry = dynamic_cast<const osg::Geometry*>(geode->getDrawable(i));
if(geometry)
{
osg::Geometry* geom = new osg::Geometry(*geometry
, osg::CopyOp::DEEP_COPY_ARRAYS | osg::CopyOp::DEEP_COPY_PRIMITIVES);
new_drawables.push_back(geom);
for( size_t i = 0; i < geom->getNumPrimitiveSets( ); ++i )
{
osg::DrawArrays* drawarray = dynamic_cast<osg::DrawArrays*>( geom->getPrimitiveSet( i ) );
if( drawarray )
{
GLint first = drawarray->getFirst();
GLint last = drawarray->getFirst()+drawarray->getCount();
// Invert vertex order.
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
if( vertices )
{
reverseWindingOrder( vertices, drawarray->getMode(), first, last );
}
if( geom->getNormalBinding( ) == osg::Geometry::BIND_PER_VERTEX )
{
osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>(geom->getNormalArray());
if( normals )
{
// First, invert the direction of the normals.
for( GLint i = first; i < last; ++i )
{
(*normals)[i] = -(*normals)[i];
}
reverseWindingOrder( normals, drawarray->getMode(), first, last );
}
}
if( geom->getColorBinding( ) == osg::Geometry::BIND_PER_VERTEX )
{
osg::Vec4Array* colors = dynamic_cast<osg::Vec4Array*>(geom->getColorArray());
if( colors )
{
reverseWindingOrder( colors, drawarray->getMode(), first, last );
}
}
for( size_t i = 0; i < geom->getNumTexCoordArrays(); ++i )
{
osg::Vec2Array* UVs = dynamic_cast<osg::Vec2Array*>(geom->getTexCoordArray(i));
if( UVs )
{
reverseWindingOrder( UVs, drawarray->getMode(), first, last );
}
}
}
}
}
}
// Now add the new geometry drawable.
for( size_t i = 0; i < new_drawables.size( ); ++i )
{
geode->addDrawable( new_drawables[i] );
}
}
/* Face record
*/
class Face : public PrimaryRecord
@@ -374,7 +474,15 @@ protected:
break;
}
case SOLID_NO_BACKFACE: // Disable backface culling
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
if( document.getReplaceDoubleSidedPolys( ) )
{
static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
}
else
{
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
}
break;
}
@@ -477,6 +585,11 @@ protected:
}
}
if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) )
{
addDrawableAndReverseWindingOrder( _geode.get() );
}
osg::StateSet* stateset = _geode->getOrCreateStateSet();
// Translucent image?
@@ -930,7 +1043,15 @@ protected:
break;
}
case SOLID_NO_BACKFACE: // Disable backface culling
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
if( document.getReplaceDoubleSidedPolys( ) )
{
static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
}
else
{
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
}
break;
}
@@ -960,6 +1081,11 @@ protected:
insertMatrixTransform(*_geode,*_matrix,_numberOfReplications);
}
if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) )
{
addDrawableAndReverseWindingOrder( _geode.get() );
}
osg::StateSet* stateset = _geode->getOrCreateStateSet();
// Translucent image?

View File

@@ -231,6 +231,7 @@ class FLTReaderWriter : public ReaderWriter
supportsOption("keepExternalReferences","Import option");
supportsOption("preserveFace","Import option");
supportsOption("preserveObject","Import option");
supportsOption("replaceDoubleSidedPolys","Import option");
supportsOption("dofAnimation","Import option");
supportsOption("billboardCenter","Import option");
supportsOption("noTextureAlphaForTransparancyBinning","Import option");
@@ -360,6 +361,9 @@ class FLTReaderWriter : public ReaderWriter
document.setPreserveObject((options->getOptionString().find("preserveObject")!=std::string::npos));
OSG_DEBUG << readerMsg << "preserveObject=" << document.getPreserveObject() << std::endl;
document.setReplaceDoubleSidedPolys((options->getOptionString().find("replaceDoubleSidedPolys")!=std::string::npos));
OSG_DEBUG << readerMsg << "replaceDoubleSidedPolys=" << document.getReplaceDoubleSidedPolys() << std::endl;
document.setDefaultDOFAnimationState((options->getOptionString().find("dofAnimation")!=std::string::npos));
OSG_DEBUG << readerMsg << "dofAnimation=" << document.getDefaultDOFAnimationState() << std::endl;