Fix duplicate geometries in FBX export.

The fix to allow the export of orphaned Geometry nodes accidentally
duplicated those geometry nodes in 'normal' scene trees. This commit
refactors the code to rely on the visitor to traverse the Geometry as
opposed to traversing the Geometry in the Geode visit and the Geometry
visit.
This commit is contained in:
Derek Quam 2018-11-13 08:47:06 -06:00
parent 85504b45f6
commit 0c1e938bc9
2 changed files with 44 additions and 92 deletions

View File

@ -468,7 +468,7 @@ WriterNodeVisitor::setControlPointAndNormalsAndUV(const GeometryList& geometryLi
for (MapIndices::iterator it = index_vert.begin(); it != index_vert.end(); ++it)
{
const osg::Geometry* pGeometry = geometryList[it->first.drawableIndex];
const osg::Geometry* pGeometry = geometryList[it->first.drawableIndex];
unsigned int vertexIndex = it->first.vertexIndex;
unsigned int normalIndex = it->first.normalIndex;
@ -603,7 +603,7 @@ void WriterNodeVisitor::buildFaces(const std::string& name,
void WriterNodeVisitor::createListTriangle(const osg::Geometry* geo,
ListTriangle& listTriangles,
bool& texcoords,
unsigned int& drawable_n)
unsigned int drawable_n)
{
unsigned int nbVertices = 0;
{
@ -638,65 +638,32 @@ void WriterNodeVisitor::createListTriangle(const osg::Geometry* geo,
}
}
void WriterNodeVisitor::apply(osg::Geode& node)
{
FbxNode* parent = _curFbxNode;
FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, node.getName().empty() ? "DefaultName" : node.getName().c_str());
_curFbxNode->AddChild(nodeFBX);
_curFbxNode = nodeFBX;
unsigned int count = node.getNumDrawables();
// collect geometries from geode
GeometryList geometryList;
for (unsigned int i = 0; i < count; ++i)
{
const osg::Geometry* g = node.getDrawable(i)->asGeometry();
if (g)
geometryList.push_back(g);
}
if(node.getStateSet()){
pushStateSet(node.getStateSet());
}
// process geometries in batch
processGeometryList(geometryList, node.getName());
if(node.getStateSet()){
popStateSet(node.getStateSet());
}
if (succeedLastApply())
traverse(node);
_curFbxNode = parent;
}
void WriterNodeVisitor::apply(osg::Geometry& geometry)
{
// here we simply create a single fbx node to assign it the mesh
// retrieved from the geometry.
// No need to push&pop the geometry state set, as it will be taken into account
// by processGeometryList()
// here we simply create a single fbx node to assign it the mesh
// retrieved from the geometry.
// create fbx node to contain the single geometry
FbxNode* parent = _curFbxNode;
FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, geometry.getName().empty() ? "Geometry" : geometry.getName().c_str());
_curFbxNode->AddChild(nodeFBX);
_curFbxNode = nodeFBX;
// create fbx node to contain the single geometry
FbxNode* parent = _curFbxNode;
FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, geometry.getName().empty() ? "Geometry" : geometry.getName().c_str());
_curFbxNode->AddChild(nodeFBX);
_curFbxNode = nodeFBX;
// process the single geometry
GeometryList geometryList;
geometryList.push_back(&geometry);
processGeometryList(geometryList, geometry.getName());
_geometryList.push_back(&geometry);
// return to parent fbx node
_curFbxNode = parent;
pushStateSet(geometry.getStateSet());
createListTriangle(&geometry, _listTriangles, _texcoords, _drawableNum++);
popStateSet(geometry.getStateSet());
osg::NodeVisitor::traverse(geometry);
if (geometry.getNumParents() == 0)
buildFaces(geometry.getName(), _geometryList, _listTriangles, _texcoords);
// return to parent fbx node
_curFbxNode = parent;
}
void WriterNodeVisitor::apply(osg::Group& node)
{
FbxNode* parent = _curFbxNode;
@ -704,7 +671,20 @@ void WriterNodeVisitor::apply(osg::Group& node)
FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, node.getName().empty() ? "DefaultName" : node.getName().c_str());
_curFbxNode->AddChild(nodeFBX);
_curFbxNode = nodeFBX;
_geometryList.clear();
_listTriangles.clear();
_texcoords = false;
_drawableNum = 0;
for (MaterialMap::iterator it = _materialMap.begin(); it != _materialMap.end(); ++it)
it->second.setIndex(-1);
_lastMaterialIndex = 0;
traverse(node);
if (_listTriangles.size() > 0)
buildFaces(node.getName(), _geometryList, _listTriangles, _texcoords);
_curFbxNode = parent;
}
@ -734,30 +714,5 @@ void WriterNodeVisitor::apply(osg::MatrixTransform& node)
_curFbxNode = parent;
}
//////////////////////////////////////////////////////////////////////////
void WriterNodeVisitor::processGeometryList(GeometryList &geometryList, const std::string& meshName)
{
ListTriangle listTriangles;
bool texcoords = false;
for (MaterialMap::iterator it = _materialMap.begin(); it != _materialMap.end(); ++it)
it->second.setIndex(-1);
_lastMaterialIndex = 0;
for (unsigned int i = 0; i < geometryList.size(); ++i)
{
const osg::Geometry* g = geometryList[i];
pushStateSet(g->getStateSet());
createListTriangle(g, listTriangles, texcoords, i);
popStateSet(g->getStateSet());
}
if (listTriangles.size() > 0){
buildFaces(meshName, geometryList, listTriangles, texcoords);
}
}
// end namespace pluginfbx
}

View File

@ -78,23 +78,17 @@ class WriterNodeVisitor: public osg::NodeVisitor
const std::string& srcDirectory) :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_pSdkManager(pSdkManager),
_succeedLastApply(true),
_pScene(pScene),
_curFbxNode(pScene->GetRootNode()),
_currentStateSet(new osg::StateSet()),
_lastMaterialIndex(0),
_lastMeshIndex(0),
_options(options),
_externalWriter(srcDirectory, osgDB::getFilePath(fileName), true, 0)
_externalWriter(srcDirectory, osgDB::getFilePath(fileName), true, 0),
_texcoords(false),
_drawableNum(0)
{}
///Tell us if last Node succeed traversing.
bool succeedLastApply() const { return _succeedLastApply; }
///Set the flag _succeedLastApply to false.
void failedApply() { _succeedLastApply = false; }
virtual void apply(osg::Geode& node);
virtual void apply(osg::Geometry& node);
virtual void apply(osg::Group& node);
virtual void apply(osg::MatrixTransform& node);
@ -195,9 +189,6 @@ class WriterNodeVisitor: public osg::NodeVisitor
private:
/// process triangles and build faces for a batch of geometries
void processGeometryList(GeometryList& geometryList, const std::string& meshName);
/**
* Fill the faces field of the mesh and call buildMesh().
* \param name the name to assign to the Fbx Mesh
@ -229,7 +220,7 @@ class WriterNodeVisitor: public osg::NodeVisitor
void createListTriangle(const osg::Geometry* geo,
ListTriangle& listTriangles,
bool& texcoords,
unsigned int& drawable_n);
unsigned int drawable_n);
///Store the material of the stateset in the MaterialMap.
int processStateSet(const osg::StateSet* stateset);
@ -264,6 +255,12 @@ class WriterNodeVisitor: public osg::NodeVisitor
unsigned int _lastMeshIndex;
const osgDB::ReaderWriter::Options* _options;
osgDB::ExternalFileWriter _externalWriter;
///Maintain geode state between visits to the geometry
GeometryList _geometryList;
ListTriangle _listTriangles;
bool _texcoords;
unsigned int _drawableNum;
};
// end namespace pluginfbx