Workaround for files exported from SoftImage that don't tag skeleton nodes correctly.

This commit is contained in:
Michael PLATINGS
2010-03-19 20:12:19 +00:00
parent f053c6c567
commit 03d5b81a6f
5 changed files with 55 additions and 12 deletions

View File

@@ -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<const KFbxNode*>& fbxSkeletons)
{
if (const KFbxGeometry* pMesh = dynamic_cast<const KFbxGeometry*>(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<const KFbxNode*> fbxSkeletons;
findLinkedFbxSkeletonNodes(pNode, fbxSkeletons);
std::map<KFbxNode*, osg::Node*> nodeMap;
BindMatrixMap boneBindMatrices;
std::map<KFbxNode*, osgAnimation::Skeleton*> skeletonMap;
ReadResult res = readFbxNode(*pSdkManager, pNode, pAnimationManager,
bIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap,
boneBindMatrices, skeletonMap, localOptions.get());
boneBindMatrices, fbxSkeletons, skeletonMap, localOptions.get());
if (res.success())
{

View File

@@ -292,6 +292,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager,
std::vector<StateSetContent>& stateSetList,
const char* szName,
BindMatrixMap& boneBindMatrices,
const std::set<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>& 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<osgAnimation::AnimationManagerBase>& pAnimationManager,
std::vector<StateSetContent>& stateSetList,
BindMatrixMap& boneBindMatrices,
const std::set<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap)
{
KFbxMesh* lMesh = dynamic_cast<KFbxMesh*>(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);
}

View File

@@ -11,6 +11,7 @@ osgDB::ReaderWriter::ReadResult readFbxMesh(
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
std::vector<StateSetContent>&,
BindMatrixMap& boneBindMatrices,
const std::set<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap);
#endif

View File

@@ -324,6 +324,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet,
std::map<KFbxNode*, osg::Node*>& nodeMap,
BindMatrixMap& boneBindMatrices,
const std::set<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>& 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<StateSetContent > 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<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>& 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();
}

View File

@@ -10,7 +10,9 @@ namespace osgAnimation
typedef std::map<std::pair<KFbxNode*, osgAnimation::RigGeometry*>, osg::Matrix> BindMatrixMap;
osgAnimation::Skeleton* getSkeleton(KFbxNode*, std::map<KFbxNode*, osgAnimation::Skeleton*>&);
osgAnimation::Skeleton* getSkeleton(KFbxNode*,
const std::set<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>&);
osgDB::ReaderWriter::ReadResult readFbxNode(
FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager,
@@ -21,6 +23,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet,
std::map<KFbxNode*, osg::Node*>& nodeMap,
BindMatrixMap& boneBindMatrices,
const std::set<const KFbxNode*>& fbxSkeletons,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap,
const osgDB::Options* options = NULL);