2.8 branch: Mergine recent changes to FBX. Revisions in this commit: r11251, r11252, r11262.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osg/MatrixTransform>
|
||||
@@ -98,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,
|
||||
@@ -142,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());
|
||||
@@ -157,14 +180,15 @@ void resolveBindMatrices(
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
osg::notify(osg::WARN) << "No vertex influences found for \"" << osgBone.getName() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
osg::notify(osg::WARN) << "No bone found for \"" << fbxBone->GetName() << "\"" << std::endl;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,15 +285,20 @@ 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())
|
||||
{
|
||||
fbxMaterialToOsgStateSet.checkInvertTransparency();
|
||||
|
||||
resolveBindMatrices(*res.getNode(), boneBindMatrices, nodeMap);
|
||||
|
||||
osg::Node* osgNode = res.getNode();
|
||||
|
||||
@@ -80,7 +80,9 @@ FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* pFbxMat)
|
||||
static_cast<float>(pFbxPhong->GetShininess().Get()));
|
||||
}
|
||||
}
|
||||
return std::make_pair(pOsgMat.release(), pOsgTex.release());
|
||||
StateSetContent result(pOsgMat.release(), pOsgTex.release());
|
||||
_kFbxMaterialMap.insert(KFbxMaterialMap::value_type(pFbxMat, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Texture2D>
|
||||
@@ -109,3 +111,34 @@ FbxMaterialToOsgStateSet::fbxTextureToOsgTexture(const KFbxTexture* fbx)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FbxMaterialToOsgStateSet::checkInvertTransparency()
|
||||
{
|
||||
int zeroAlpha = 0, oneAlpha = 0;
|
||||
for (KFbxMaterialMap::const_iterator it = _kFbxMaterialMap.begin(); it != _kFbxMaterialMap.end(); ++it)
|
||||
{
|
||||
const osg::Material* pMaterial = it->second.first;
|
||||
float alpha = pMaterial->getDiffuse(osg::Material::FRONT).a();
|
||||
if (alpha > 0.999f)
|
||||
{
|
||||
++oneAlpha;
|
||||
}
|
||||
else if (alpha < 0.001f)
|
||||
{
|
||||
++zeroAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
if (zeroAlpha > oneAlpha)
|
||||
{
|
||||
//Transparency values seem to be back to front so invert them.
|
||||
|
||||
for (KFbxMaterialMap::const_iterator it = _kFbxMaterialMap.begin(); it != _kFbxMaterialMap.end(); ++it)
|
||||
{
|
||||
osg::Material* pMaterial = it->second.first;
|
||||
osg::Vec4 diffuse = pMaterial->getDiffuse(osg::Material::FRONT);
|
||||
diffuse.a() = 1.0f - diffuse.a();
|
||||
pMaterial->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ public:
|
||||
FbxMaterialToOsgStateSet::FbxMaterialToOsgStateSet(const std::string& dir, const osgDB::ReaderWriter::Options* options) :
|
||||
_options(options),
|
||||
_dir(dir) {}
|
||||
|
||||
void checkInvertTransparency();
|
||||
private:
|
||||
//Convert a texture fbx to an osg texture.
|
||||
osg::ref_ptr<osg::Texture2D>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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::ReaderWriter::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();
|
||||
}
|
||||
|
||||
@@ -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::ReaderWriter::Options* options = NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user