Fix for some FBX files with multiple meshes bound to a bone.
This commit is contained in:
parent
ace8dad2c3
commit
65489693d9
@ -14,7 +14,9 @@
|
||||
#include <osgDB/Registry>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/Skeleton>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( disable : 4505 )
|
||||
@ -96,6 +98,77 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void resolveBindMatrices(
|
||||
osg::Node& root,
|
||||
const BindMatrixMap& boneBindMatrices,
|
||||
const std::map<KFbxNode*, osg::Node*>& nodeMap)
|
||||
{
|
||||
std::set<std::string> nodeNames;
|
||||
for (std::map<KFbxNode*, osg::Node*>::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<KFbxNode*, osg::Node*>::const_iterator nodeIt = nodeMap.find(fbxBone);
|
||||
if (nodeIt != nodeMap.end())
|
||||
{
|
||||
const osg::Matrix bindMatrix = it->second;
|
||||
osgAnimation::Bone& osgBone = dynamic_cast<osgAnimation::Bone&>(*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<KFbxNode*, osg::Node*> nodeMap;
|
||||
std::map<KFbxNode*, osg::Matrix> boneBindMatrices;
|
||||
BindMatrixMap boneBindMatrices;
|
||||
std::map<KFbxNode*, osgAnimation::Skeleton*> 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<KFbxNode*, osg::Matrix>::const_iterator it = boneBindMatrices.begin();
|
||||
it != boneBindMatrices.end(); ++it)
|
||||
{
|
||||
std::map<KFbxNode*, osg::Node*>::iterator nodeIt = nodeMap.find(it->first);
|
||||
if (nodeIt != nodeMap.end())
|
||||
{
|
||||
osgAnimation::Bone& osgBone = dynamic_cast<osgAnimation::Bone&>(*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);
|
||||
|
@ -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<osgAnimation::AnimationManagerBase>& pAnimationManager,
|
||||
std::vector<StateSetContent>& stateSetList,
|
||||
const char* szName,
|
||||
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
|
||||
BindMatrixMap& boneBindMatrices,
|
||||
std::map<KFbxNode*, osgAnimation::Skeleton*>& 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<KFbxNode*, osg::Matrix>(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<osgAnimation::RigGeometry&>(
|
||||
*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<osgAnimation::AnimationManagerBase>& pAnimationManager,
|
||||
std::vector<StateSetContent>& stateSetList,
|
||||
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
|
||||
BindMatrixMap& boneBindMatrices,
|
||||
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap)
|
||||
{
|
||||
KFbxMesh* lMesh = dynamic_cast<KFbxMesh*>(pNode->GetNodeAttribute());
|
||||
|
@ -4,13 +4,13 @@
|
||||
#include <fbxfilesdk/fbxfilesdk_def.h>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osg/Material>
|
||||
#include "fbxMaterialToOsgStateSet.h"
|
||||
#include "fbxRNode.h"
|
||||
osgDB::ReaderWriter::ReadResult readFbxMesh(
|
||||
FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager,
|
||||
FBXFILESDK_NAMESPACE::KFbxNode* pNode,
|
||||
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
|
||||
std::vector<StateSetContent>&,
|
||||
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
|
||||
BindMatrixMap& boneBindMatrices,
|
||||
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap);
|
||||
|
||||
#endif
|
||||
|
@ -323,7 +323,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
|
||||
bool& bIsBone, int& nLightCount,
|
||||
FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet,
|
||||
std::map<KFbxNode*, osg::Node*>& nodeMap,
|
||||
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
|
||||
BindMatrixMap& boneBindMatrices,
|
||||
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap,
|
||||
const osgDB::Options* options)
|
||||
{
|
||||
|
@ -5,8 +5,11 @@
|
||||
namespace osgAnimation
|
||||
{
|
||||
class AnimationManagerBase;
|
||||
class RigGeometry;
|
||||
}
|
||||
|
||||
typedef std::map<std::pair<KFbxNode*, osgAnimation::RigGeometry*>, osg::Matrix> BindMatrixMap;
|
||||
|
||||
osgAnimation::Skeleton* getSkeleton(KFbxNode*, std::map<KFbxNode*, osgAnimation::Skeleton*>&);
|
||||
|
||||
osgDB::ReaderWriter::ReadResult readFbxNode(
|
||||
@ -17,7 +20,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
|
||||
int& nLightCount,
|
||||
FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet,
|
||||
std::map<KFbxNode*, osg::Node*>& nodeMap,
|
||||
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
|
||||
BindMatrixMap& boneBindMatrices,
|
||||
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap,
|
||||
const osgDB::Options* options = NULL);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user