Fix for some FBX files with multiple meshes bound to a bone.

This commit is contained in:
Michael PLATINGS 2010-03-04 16:27:19 +00:00
parent ace8dad2c3
commit 65489693d9
5 changed files with 96 additions and 25 deletions

View File

@ -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);

View File

@ -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());

View File

@ -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

View File

@ -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)
{

View File

@ -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);