diff --git a/src/osgPlugins/fbx/ReaderWriterFBX.cpp b/src/osgPlugins/fbx/ReaderWriterFBX.cpp index 0bd6ead45..955502449 100644 --- a/src/osgPlugins/fbx/ReaderWriterFBX.cpp +++ b/src/osgPlugins/fbx/ReaderWriterFBX.cpp @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #if defined(_MSC_VER) #pragma warning( disable : 4505 ) @@ -96,6 +98,77 @@ public: } }; +void resolveBindMatrices( + osg::Node& root, + const BindMatrixMap& boneBindMatrices, + const std::map& nodeMap) +{ + std::set nodeNames; + for (std::map::const_iterator it = nodeMap.begin(); it != nodeMap.end(); ++it) + { + nodeNames.insert(it->second->getName()); + } + + for (BindMatrixMap::const_iterator it = boneBindMatrices.begin(); + it != boneBindMatrices.end();) + { + KFbxNode* const fbxBone = it->first.first; + std::map::const_iterator nodeIt = nodeMap.find(fbxBone); + if (nodeIt != nodeMap.end()) + { + const osg::Matrix bindMatrix = it->second; + osgAnimation::Bone& osgBone = dynamic_cast(*nodeIt->second); + osgBone.setInvBindMatrixInSkeletonSpace(bindMatrix); + + ++it; + for (; it != boneBindMatrices.end() && it->first.first == fbxBone; ++it) + { + if (it->second != bindMatrix) + { + std::string name; + for (int i = 0;; ++i) + { + std::stringstream ss; + ss << osgBone.getName() << '_' << i; + name = ss.str(); + if (nodeNames.insert(name).second) + { + break; + } + } + osgAnimation::Bone* newBone = new osgAnimation::Bone(name); + newBone->setDefaultUpdateCallback(); + newBone->setInvBindMatrixInSkeletonSpace(it->second); + osgBone.addChild(newBone); + + osgAnimation::RigGeometry* pRigGeometry = it->first.second; + + osgAnimation::VertexInfluenceMap* vertexInfluences = pRigGeometry->getInfluenceMap(); + + osgAnimation::VertexInfluenceMap::iterator vimIt = vertexInfluences->find(osgBone.getName()); + if (vimIt != vertexInfluences->end()) + { + osgAnimation::VertexInfluence vi; + vi.swap(vimIt->second); + vertexInfluences->erase(vimIt); + osgAnimation::VertexInfluence& vi2 = (*vertexInfluences)[name]; + vi.swap(vi2); + vi2.setName(name); + } + else + { + assert(0); + } + } + } + } + else + { + assert(0); + } + } +} + osgDB::ReaderWriter::ReadResult ReaderWriterFBX::readNode(const std::string& filenameInit, const Options* options) const @@ -189,7 +262,7 @@ ReaderWriterFBX::readNode(const std::string& filenameInit, FbxMaterialToOsgStateSet fbxMaterialToOsgStateSet(filePath, localOptions.get()); std::map nodeMap; - std::map boneBindMatrices; + BindMatrixMap boneBindMatrices; std::map skeletonMap; ReadResult res = readFbxNode(*pSdkManager, pNode, pAnimationManager, bIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, @@ -197,20 +270,7 @@ ReaderWriterFBX::readNode(const std::string& filenameInit, if (res.success()) { - for (std::map::const_iterator it = boneBindMatrices.begin(); - it != boneBindMatrices.end(); ++it) - { - std::map::iterator nodeIt = nodeMap.find(it->first); - if (nodeIt != nodeMap.end()) - { - osgAnimation::Bone& osgBone = dynamic_cast(*nodeIt->second); - osgBone.setInvBindMatrixInSkeletonSpace(it->second); - } - else - { - assert(0); - } - } + resolveBindMatrices(*res.getNode(), boneBindMatrices, nodeMap); osg::Node* osgNode = res.getNode(); osgNode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON); diff --git a/src/osgPlugins/fbx/fbxRMesh.cpp b/src/osgPlugins/fbx/fbxRMesh.cpp index 5c13812cc..60205a032 100644 --- a/src/osgPlugins/fbx/fbxRMesh.cpp +++ b/src/osgPlugins/fbx/fbxRMesh.cpp @@ -260,12 +260,22 @@ void readAnimation(KFbxNode* pNode, const std::string& targetName, } } +void addBindMatrix( + BindMatrixMap& boneBindMatrices, + KFbxNode* pBone, + const osg::Matrix& bindMatrix, + osgAnimation::RigGeometry* pRigGeometry) +{ + boneBindMatrices.insert(BindMatrixMap::value_type( + BindMatrixMap::key_type(pBone, pRigGeometry), bindMatrix)); +} + osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, KFbxNode* pNode, KFbxMesh* fbxMesh, osg::ref_ptr& pAnimationManager, std::vector& stateSetList, const char* szName, - std::map& boneBindMatrices, + BindMatrixMap& boneBindMatrices, std::map& skeletonMap) { GeometryMap geometryMap; @@ -440,10 +450,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, pCluster->GetTransformLinkMatrix(transformLink); KFbxXMatrix transformLinkInverse = transformLink.Inverse(); const double* pTransformLinkInverse = transformLinkInverse; - if (!boneBindMatrices.insert(std::pair(pBone, osg::Matrix(pTransformLinkInverse))).second) - { - osg::notify(osg::WARN) << "Multiple meshes attached to a bone - bind matrices may be incorrect." << std::endl; - } + osg::Matrix bindMatrix(pTransformLinkInverse); int nIndices = pCluster->GetControlPointIndicesCount(); int* pIndices = pCluster->GetControlPointIndices(); @@ -463,6 +470,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, osgAnimation::RigGeometry& rig = dynamic_cast( *old2newGeometryMap[gi.first]); + addBindMatrix(boneBindMatrices, pBone, bindMatrix, &rig); osgAnimation::VertexInfluenceMap& vim = *rig.getInfluenceMap(); osgAnimation::VertexInfluence& vi = @@ -603,7 +611,7 @@ osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxSdkManager& pSdkManager, KFbxNode* pNode, osg::ref_ptr& pAnimationManager, std::vector& stateSetList, - std::map& boneBindMatrices, + BindMatrixMap& boneBindMatrices, std::map& skeletonMap) { KFbxMesh* lMesh = dynamic_cast(pNode->GetNodeAttribute()); diff --git a/src/osgPlugins/fbx/fbxRMesh.h b/src/osgPlugins/fbx/fbxRMesh.h index 97c3d3c48..40200883e 100644 --- a/src/osgPlugins/fbx/fbxRMesh.h +++ b/src/osgPlugins/fbx/fbxRMesh.h @@ -4,13 +4,13 @@ #include #include #include -#include "fbxMaterialToOsgStateSet.h" +#include "fbxRNode.h" osgDB::ReaderWriter::ReadResult readFbxMesh( FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager, FBXFILESDK_NAMESPACE::KFbxNode* pNode, osg::ref_ptr& pAnimationManager, std::vector&, - std::map& boneBindMatrices, + BindMatrixMap& boneBindMatrices, std::map& skeletonMap); #endif diff --git a/src/osgPlugins/fbx/fbxRNode.cpp b/src/osgPlugins/fbx/fbxRNode.cpp index a5a9bcd4b..06ab1e5fb 100644 --- a/src/osgPlugins/fbx/fbxRNode.cpp +++ b/src/osgPlugins/fbx/fbxRNode.cpp @@ -323,7 +323,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode( bool& bIsBone, int& nLightCount, FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, std::map& nodeMap, - std::map& boneBindMatrices, + BindMatrixMap& boneBindMatrices, std::map& skeletonMap, const osgDB::Options* options) { diff --git a/src/osgPlugins/fbx/fbxRNode.h b/src/osgPlugins/fbx/fbxRNode.h index 20a5f26c0..cbf91b137 100644 --- a/src/osgPlugins/fbx/fbxRNode.h +++ b/src/osgPlugins/fbx/fbxRNode.h @@ -5,8 +5,11 @@ namespace osgAnimation { class AnimationManagerBase; + class RigGeometry; } +typedef std::map, osg::Matrix> BindMatrixMap; + osgAnimation::Skeleton* getSkeleton(KFbxNode*, std::map&); osgDB::ReaderWriter::ReadResult readFbxNode( @@ -17,7 +20,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode( int& nLightCount, FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, std::map& nodeMap, - std::map& boneBindMatrices, + BindMatrixMap& boneBindMatrices, std::map& skeletonMap, const osgDB::Options* options = NULL);