diff --git a/src/osgPlugins/fbx/ReaderWriterFBX.cpp b/src/osgPlugins/fbx/ReaderWriterFBX.cpp index 8364c707d..2f434bddb 100644 --- a/src/osgPlugins/fbx/ReaderWriterFBX.cpp +++ b/src/osgPlugins/fbx/ReaderWriterFBX.cpp @@ -97,6 +97,30 @@ public: } }; +//Some files don't correctly mark their skeleton nodes, so this function infers +//them from the nodes that skin deformers linked to. +void findLinkedFbxSkeletonNodes(KFbxNode* pNode, std::set& fbxSkeletons) +{ + if (const KFbxGeometry* pMesh = dynamic_cast(pNode->GetNodeAttribute())) + { + for (int i = 0; i < pMesh->GetDeformerCount(KFbxDeformer::eSKIN); ++i) + { + const KFbxSkin* pSkin = (const KFbxSkin*)pMesh->GetDeformer(i, KFbxDeformer::eSKIN); + + for (int j = 0; j < pSkin->GetClusterCount(); ++j) + { + const KFbxNode* pSkeleton = pSkin->GetCluster(j)->GetLink(); + fbxSkeletons.insert(pSkeleton); + } + } + } + + for (int i = 0; i < pNode->GetChildCount(); ++i) + { + findLinkedFbxSkeletonNodes(pNode->GetChild(i), fbxSkeletons); + } +} + void resolveBindMatrices( osg::Node& root, const BindMatrixMap& boneBindMatrices, @@ -141,7 +165,7 @@ void resolveBindMatrices( osgBone.addChild(newBone); osgAnimation::RigGeometry* pRigGeometry = it->first.second; - + osgAnimation::VertexInfluenceMap* vertexInfluences = pRigGeometry->getInfluenceMap(); osgAnimation::VertexInfluenceMap::iterator vimIt = vertexInfluences->find(osgBone.getName()); @@ -261,12 +285,15 @@ ReaderWriterFBX::readNode(const std::string& filenameInit, std::string filePath = osgDB::getFilePath(filename); FbxMaterialToOsgStateSet fbxMaterialToOsgStateSet(filePath, localOptions.get()); + std::set fbxSkeletons; + findLinkedFbxSkeletonNodes(pNode, fbxSkeletons); + std::map nodeMap; BindMatrixMap boneBindMatrices; std::map skeletonMap; ReadResult res = readFbxNode(*pSdkManager, pNode, pAnimationManager, bIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, - boneBindMatrices, skeletonMap, localOptions.get()); + boneBindMatrices, fbxSkeletons, skeletonMap, localOptions.get()); if (res.success()) { diff --git a/src/osgPlugins/fbx/fbxRMesh.cpp b/src/osgPlugins/fbx/fbxRMesh.cpp index 209dc5366..17c6cb3f1 100644 --- a/src/osgPlugins/fbx/fbxRMesh.cpp +++ b/src/osgPlugins/fbx/fbxRMesh.cpp @@ -292,6 +292,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, std::vector& stateSetList, const char* szName, BindMatrixMap& boneBindMatrices, + const std::set& fbxSkeletons, std::map& skeletonMap) { GeometryMap geometryMap; @@ -299,7 +300,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, osg::Geode* pGeode = new osg::Geode; pGeode->setName(szName); - const KFbxLayer* pFbxLayer = 0; + const KFbxLayer* pFbxLayer = fbxMesh->GetLayer(0); const KFbxLayerElementNormal* pFbxNormals = 0; const KFbxLayerElementUV* pFbxUVs = 0; const KFbxLayerElementVertexColor* pFbxColors = 0; @@ -307,7 +308,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, const KFbxVector4* pFbxVertices = fbxMesh->GetControlPoints(); - if (pFbxLayer = fbxMesh->GetLayer(0)) + if (pFbxLayer) { pFbxNormals = pFbxLayer->GetNormals(); pFbxColors = pFbxLayer->GetVertexColors(); @@ -614,7 +615,8 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN); if (pSkin->GetClusterCount()) { - osgAnimation::Skeleton* pSkeleton = getSkeleton(pSkin->GetCluster(0)->GetLink(), skeletonMap); + osgAnimation::Skeleton* pSkeleton = getSkeleton( + pSkin->GetCluster(0)->GetLink(), fbxSkeletons, skeletonMap); pSkeleton->addChild(pResult); return osgDB::ReaderWriter::ReadResult::FILE_LOADED; } @@ -628,6 +630,7 @@ osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxSdkManager& pSdkManager, osg::ref_ptr& pAnimationManager, std::vector& stateSetList, BindMatrixMap& boneBindMatrices, + const std::set& fbxSkeletons, std::map& skeletonMap) { KFbxMesh* lMesh = dynamic_cast(pNode->GetNodeAttribute()); @@ -638,5 +641,5 @@ osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxSdkManager& pSdkManager, } return readMesh(pSdkManager, pNode, lMesh, pAnimationManager, stateSetList, - pNode->GetName(), boneBindMatrices, skeletonMap); + pNode->GetName(), boneBindMatrices, fbxSkeletons, skeletonMap); } diff --git a/src/osgPlugins/fbx/fbxRMesh.h b/src/osgPlugins/fbx/fbxRMesh.h index 40200883e..ffac5dbcc 100644 --- a/src/osgPlugins/fbx/fbxRMesh.h +++ b/src/osgPlugins/fbx/fbxRMesh.h @@ -11,6 +11,7 @@ osgDB::ReaderWriter::ReadResult readFbxMesh( osg::ref_ptr& pAnimationManager, std::vector&, BindMatrixMap& boneBindMatrices, + const std::set& fbxSkeletons, std::map& skeletonMap); #endif diff --git a/src/osgPlugins/fbx/fbxRNode.cpp b/src/osgPlugins/fbx/fbxRNode.cpp index 06ab1e5fb..91356ed95 100644 --- a/src/osgPlugins/fbx/fbxRNode.cpp +++ b/src/osgPlugins/fbx/fbxRNode.cpp @@ -324,6 +324,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode( FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, std::map& nodeMap, BindMatrixMap& boneBindMatrices, + const std::set& fbxSkeletons, std::map& skeletonMap, const osgDB::Options* options) { @@ -350,6 +351,11 @@ osgDB::ReaderWriter::ReadResult readFbxNode( } } + if (!bIsBone && fbxSkeletons.find(pNode) != fbxSkeletons.end()) + { + bIsBone = true; + } + unsigned nMaterials = pNode->GetMaterialCount(); std::vector stateSetList; @@ -377,7 +383,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode( osgDB::ReaderWriter::ReadResult childResult = readFbxNode( pSdkManager, pChildNode, pAnimationManager, bChildIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, - boneBindMatrices, skeletonMap, options); + boneBindMatrices, fbxSkeletons, skeletonMap, options); if (childResult.error()) { return childResult; @@ -425,7 +431,8 @@ osgDB::ReaderWriter::ReadResult readFbxNode( { size_t bindMatrixCount = boneBindMatrices.size(); osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pSdkManager, - pNode, pAnimationManager, stateSetList, boneBindMatrices, skeletonMap); + pNode, pAnimationManager, stateSetList, boneBindMatrices, + fbxSkeletons, skeletonMap); if (meshRes.error()) { return meshRes; @@ -490,7 +497,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode( osg::Group* pAddChildrenTo = osgGroup.get(); if (bCreateSkeleton) { - osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, skeletonMap); + osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, fbxSkeletons, skeletonMap); osgSkeleton->setDefaultUpdateCallback(); pAddChildrenTo->addChild(osgSkeleton); pAddChildrenTo = osgSkeleton; @@ -510,12 +517,14 @@ osgDB::ReaderWriter::ReadResult readFbxNode( } osgAnimation::Skeleton* getSkeleton(KFbxNode* fbxNode, + const std::set& fbxSkeletons, std::map& skeletonMap) { //Find the first non-skeleton ancestor of the node. while (fbxNode && - fbxNode->GetNodeAttribute() && - fbxNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eSKELETON) + ((fbxNode->GetNodeAttribute() && + fbxNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eSKELETON) || + fbxSkeletons.find(fbxNode) != fbxSkeletons.end())) { fbxNode = fbxNode->GetParent(); } diff --git a/src/osgPlugins/fbx/fbxRNode.h b/src/osgPlugins/fbx/fbxRNode.h index cbf91b137..287ad5319 100644 --- a/src/osgPlugins/fbx/fbxRNode.h +++ b/src/osgPlugins/fbx/fbxRNode.h @@ -10,7 +10,9 @@ namespace osgAnimation typedef std::map, osg::Matrix> BindMatrixMap; -osgAnimation::Skeleton* getSkeleton(KFbxNode*, std::map&); +osgAnimation::Skeleton* getSkeleton(KFbxNode*, + const std::set& fbxSkeletons, + std::map&); osgDB::ReaderWriter::ReadResult readFbxNode( FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager, @@ -21,6 +23,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode( FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, std::map& nodeMap, BindMatrixMap& boneBindMatrices, + const std::set& fbxSkeletons, std::map& skeletonMap, const osgDB::Options* options = NULL);