From ef8891351f7c4481e7387cb30c098491054bd750 Mon Sep 17 00:00:00 2001 From: Riccardo Corsi Date: Wed, 20 Dec 2017 09:52:50 +0100 Subject: [PATCH] Fbx writer: added support to convert geometries directly attached as node, without geodes. --- src/osgPlugins/fbx/WriterNodeVisitor.cpp | 96 ++++++++++++++++++------ src/osgPlugins/fbx/WriterNodeVisitor.h | 16 +++- 2 files changed, 84 insertions(+), 28 deletions(-) diff --git a/src/osgPlugins/fbx/WriterNodeVisitor.cpp b/src/osgPlugins/fbx/WriterNodeVisitor.cpp index f398010d8..eb1ebba66 100644 --- a/src/osgPlugins/fbx/WriterNodeVisitor.cpp +++ b/src/osgPlugins/fbx/WriterNodeVisitor.cpp @@ -444,7 +444,7 @@ WriterNodeVisitor::setLayerTextureAndMaterial(FbxMesh* mesh) } void -WriterNodeVisitor::setControlPointAndNormalsAndUV(const osg::Geode& geo, +WriterNodeVisitor::setControlPointAndNormalsAndUV(const GeometryList& geometryList, MapIndices& index_vert, bool texcoords, FbxMesh* mesh) @@ -468,7 +468,7 @@ WriterNodeVisitor::setControlPointAndNormalsAndUV(const osg::Geode& geo, for (MapIndices::iterator it = index_vert.begin(); it != index_vert.end(); ++it) { - const osg::Geometry* pGeometry = geo.getDrawable(it->first.drawableIndex)->asGeometry(); + const osg::Geometry* pGeometry = geometryList[it->first.drawableIndex]; unsigned int vertexIndex = it->first.vertexIndex; unsigned int normalIndex = it->first.normalIndex; @@ -562,12 +562,13 @@ WriterNodeVisitor::setControlPointAndNormalsAndUV(const osg::Geode& geo, } } -void WriterNodeVisitor::buildFaces(const osg::Geode& geo, +void WriterNodeVisitor::buildFaces(const std::string& name, + const GeometryList& geometryList, ListTriangle& listTriangles, bool texcoords) { MapIndices index_vert; - FbxMesh* mesh = FbxMesh::Create(_pSdkManager, geo.getName().c_str()); + FbxMesh* mesh = FbxMesh::Create(_pSdkManager, name.c_str()); _curFbxNode->AddNodeAttribute(mesh); _curFbxNode->SetShadingMode(FbxNode::eTextureShading); FbxLayer* lLayer = mesh->GetLayer(0); @@ -596,7 +597,7 @@ void WriterNodeVisitor::buildFaces(const osg::Geode& geo, addPolygon(mesh, index_vert, it->first, it->second); mesh->EndPolygon(); } - setControlPointAndNormalsAndUV(geo, index_vert, texcoords, mesh); + setControlPointAndNormalsAndUV(geometryList, index_vert, texcoords, mesh); } void WriterNodeVisitor::createListTriangle(const osg::Geometry* geo, @@ -643,37 +644,59 @@ void WriterNodeVisitor::apply(osg::Geode& node) FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, node.getName().empty() ? "DefaultName" : node.getName().c_str()); _curFbxNode->AddChild(nodeFBX); _curFbxNode = nodeFBX; + + unsigned int count = node.getNumDrawables(); - ListTriangle listTriangles; - bool texcoords = false; - for (MaterialMap::iterator it = _materialMap.begin(); it != _materialMap.end(); ++it) - it->second.setIndex(-1); - _lastMaterialIndex = 0; + + // 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()); } - for (unsigned int i = 0; i < count; ++i) - { - const osg::Geometry* g = node.getDrawable(i)->asGeometry(); - if (g != NULL) - { - pushStateSet(g->getStateSet()); - createListTriangle(g, listTriangles, texcoords, i); - popStateSet(g->getStateSet()); - } - } + + // process geometries in batch + ProcessGeometryList(geometryList, node.getName()); + if(node.getStateSet()){ popStateSet(node.getStateSet()); } - if (count > 0) - { - buildFaces(node, listTriangles, texcoords); - } + 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() + + // 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()); + + // return to parent fbx node + _curFbxNode = parent; +} + + void WriterNodeVisitor::apply(osg::Group& node) { FbxNode* parent = _curFbxNode; @@ -711,5 +734,30 @@ 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 } diff --git a/src/osgPlugins/fbx/WriterNodeVisitor.h b/src/osgPlugins/fbx/WriterNodeVisitor.h index a05c55c49..a92a55a83 100644 --- a/src/osgPlugins/fbx/WriterNodeVisitor.h +++ b/src/osgPlugins/fbx/WriterNodeVisitor.h @@ -62,6 +62,7 @@ struct VertexIndex typedef std::vector > ListTriangle; //the int is the drawable of the triangle typedef std::map MapIndices; ///< Map OSG indices to FBX mesh indices +typedef std::vector GeometryList; // a list of geometries to process in batch namespace pluginfbx { @@ -94,9 +95,10 @@ class WriterNodeVisitor: public osg::NodeVisitor 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); - + void traverse (osg::Node& node) { pushStateSet(node.getStateSet()); @@ -192,13 +194,19 @@ 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 geo is the geode which contains the vertices and faces. + * \param name the name to assign to the Fbx Mesh + * \param geometryList is the list of geometries which contains the vertices and faces. * \param listTriangles contain all the mesh's faces. * \param texcoords tell us if we have to handle texture coordinates. */ - void buildFaces(const osg::Geode& geo, + void buildFaces(const std::string& name, + const GeometryList& geometryList, ListTriangle& listTriangles, bool texcoords); @@ -206,7 +214,7 @@ class WriterNodeVisitor: public osg::NodeVisitor void setLayerTextureAndMaterial(FbxMesh* mesh); /// Set Vertices, normals, and UVs - void setControlPointAndNormalsAndUV(const osg::Geode& geo, + void setControlPointAndNormalsAndUV(const GeometryList& geometryList, MapIndices& index_vert, bool texcoords, FbxMesh* fbxMesh);