This commit is contained in:
Michael PLATINGS 2010-03-03 16:14:04 +00:00
parent 315e0521c9
commit fd6f3edf15
5 changed files with 179 additions and 196 deletions

View File

@ -8,7 +8,6 @@
#include <osg/PositionAttitudeTransform> #include <osg/PositionAttitudeTransform>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osgDB/ConvertUTF> #include <osgDB/ConvertUTF>
#include <osgDB/FileNameUtils> #include <osgDB/FileNameUtils>
#include <osgDB/FileUtils> #include <osgDB/FileUtils>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
@ -27,43 +26,6 @@
#include "fbxMaterialToOsgStateSet.h" #include "fbxMaterialToOsgStateSet.h"
#include "WriterNodeVisitor.h" #include "WriterNodeVisitor.h"
#if defined(WIN32) && !defined(__CYGWIN__)
#define WIN32_LEAN_AND_MEAN
//For MultiByteToWideChar
#include <Windows.h>
#endif
// This function belongs in osgDB. Delete this function and use the osgDB
// version once Robert accepts the submission.
std::string convertStringFromCurrentCodePageToUTF8(const std::string& str)
{
#if defined(WIN32) && !defined(__CYGWIN__)
if (str.length() == 0)
{
return std::string();
}
int utf16Length = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), 0, 0);
if (utf16Length <= 0)
{
osg::notify(osg::WARN) << "Cannot convert multi-byte string to UTF-8." << std::endl;
return std::string();
}
std::wstring sUTF16(utf16Length, L'\0');
utf16Length = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), &sUTF16[0], utf16Length);
if (utf16Length <= 0)
{
osg::notify(osg::WARN) << "Cannot convert multi-byte string to UTF-8." << std::endl;
return std::string();
}
return osgDB::convertUTF16toUTF8(sUTF16);
#else
return str;
#endif
}
/// Returns true if the given node is a basic root group with no special information. /// Returns true if the given node is a basic root group with no special information.
/// Used in conjunction with UseFbxRoot option. /// Used in conjunction with UseFbxRoot option.
/// Identity transforms are considered as basic root nodes. /// Identity transforms are considered as basic root nodes.
@ -161,7 +123,7 @@ ReaderWriterFBX::readNode(const std::string& filenameInit,
#ifdef OSG_USE_UTF8_FILENAME #ifdef OSG_USE_UTF8_FILENAME
const std::string& utf8filename(filename); const std::string& utf8filename(filename);
#else #else
std::string utf8filename(convertStringFromCurrentCodePageToUTF8(filename)); std::string utf8filename(osgDB::convertStringFromCurrentCodePageToUTF8(filename));
#endif #endif
int fileFormat; int fileFormat;
@ -197,9 +159,9 @@ ReaderWriterFBX::readNode(const std::string& filenameInit,
if (KFbxNode* pNode = pScene->GetRootNode()) if (KFbxNode* pNode = pScene->GetRootNode())
{ {
pScene->SetCurrentTake(pScene->GetCurrentTakeName()); pScene->SetCurrentTake(pScene->GetCurrentTakeName());
bool useFbxRoot = false; bool useFbxRoot = false;
if (options) if (options)
{ {
std::istringstream iss(options->getOptionString()); std::istringstream iss(options->getOptionString());
@ -226,33 +188,33 @@ ReaderWriterFBX::readNode(const std::string& filenameInit,
std::string filePath = osgDB::getFilePath(filename); std::string filePath = osgDB::getFilePath(filename);
FbxMaterialToOsgStateSet fbxMaterialToOsgStateSet(filePath, localOptions.get()); FbxMaterialToOsgStateSet fbxMaterialToOsgStateSet(filePath, localOptions.get());
std::map<KFbxNode*, osg::Node*> nodeMap; std::map<KFbxNode*, osg::Node*> nodeMap;
std::map<KFbxNode*, osg::Matrix> boneBindMatrices; std::map<KFbxNode*, osg::Matrix> boneBindMatrices;
std::map<KFbxNode*, osgAnimation::Skeleton*> skeletonMap; std::map<KFbxNode*, osgAnimation::Skeleton*> skeletonMap;
ReadResult res = readFbxNode(*pSdkManager, pNode, pAnimationManager, ReadResult res = readFbxNode(*pSdkManager, pNode, pAnimationManager,
bIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, bIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap,
boneBindMatrices, skeletonMap, localOptions.get()); boneBindMatrices, skeletonMap, localOptions.get());
if (res.success()) if (res.success())
{ {
for (std::map<KFbxNode*, osg::Matrix>::const_iterator it = boneBindMatrices.begin(); for (std::map<KFbxNode*, osg::Matrix>::const_iterator it = boneBindMatrices.begin();
it != boneBindMatrices.end(); ++it) it != boneBindMatrices.end(); ++it)
{ {
std::map<KFbxNode*, osg::Node*>::iterator nodeIt = nodeMap.find(it->first); std::map<KFbxNode*, osg::Node*>::iterator nodeIt = nodeMap.find(it->first);
if (nodeIt != nodeMap.end()) if (nodeIt != nodeMap.end())
{ {
osgAnimation::Bone& osgBone = dynamic_cast<osgAnimation::Bone&>(*nodeIt->second); osgAnimation::Bone& osgBone = dynamic_cast<osgAnimation::Bone&>(*nodeIt->second);
osgBone.setInvBindMatrixInSkeletonSpace(it->second); osgBone.setInvBindMatrixInSkeletonSpace(it->second);
} }
else else
{ {
assert(0); assert(0);
} }
} }
osg::Node* osgNode = res.getNode(); osg::Node* osgNode = res.getNode();
osgNode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON); osgNode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON);
osgNode->getOrCreateStateSet()->setMode(GL_NORMALIZE,osg::StateAttribute::ON); osgNode->getOrCreateStateSet()->setMode(GL_NORMALIZE,osg::StateAttribute::ON);
if (pAnimationManager.valid()) if (pAnimationManager.valid())
{ {
@ -327,7 +289,7 @@ ReaderWriterFBX::readNode(const std::string& filenameInit,
} }
catch (...) catch (...)
{ {
osg::notify(osg::WARN) << "Exception thrown while importing \"" << filenameInit << '\"' << std::endl; osg::notify(osg::WARN) << "Exception thrown while importing \"" << filenameInit << '\"' << std::endl;
} }
return ReadResult::ERROR_IN_READING_FILE; return ReadResult::ERROR_IN_READING_FILE;
@ -404,7 +366,7 @@ osgDB::ReaderWriter::WriteResult ReaderWriterFBX::writeNode(
#ifdef OSG_USE_UTF8_FILENAME #ifdef OSG_USE_UTF8_FILENAME
const std::string& utf8filename(filename); const std::string& utf8filename(filename);
#else #else
std::string utf8filename(convertStringFromCurrentCodePageToUTF8(filename)); std::string utf8filename(osgDB::convertStringFromCurrentCodePageToUTF8(filename));
#endif #endif
if (!lExporter->Initialize(utf8filename.c_str())) if (!lExporter->Initialize(utf8filename.c_str()))

View File

@ -261,12 +261,12 @@ void readAnimation(KFbxNode* pNode, const std::string& targetName,
} }
osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager, osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager,
KFbxNode* pNode, KFbxMesh* fbxMesh, KFbxNode* pNode, KFbxMesh* fbxMesh,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
std::vector<StateSetContent>& stateSetList, std::vector<StateSetContent>& stateSetList,
const char* szName, const char* szName,
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices, std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap) std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap)
{ {
GeometryMap geometryMap; GeometryMap geometryMap;
@ -413,7 +413,7 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager,
{ {
osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry(); osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
osgAnimation::RigGeometry* pRig = new osgAnimation::RigGeometry; osgAnimation::RigGeometry* pRig = new osgAnimation::RigGeometry;
pRig->setSourceGeometry(pGeometry); pRig->setSourceGeometry(pGeometry);
pRig->copyFrom(*pGeometry); pRig->copyFrom(*pGeometry);
old2newGeometryMap.insert(GeometryRigGeometryMap::value_type( old2newGeometryMap.insert(GeometryRigGeometryMap::value_type(
@ -433,17 +433,17 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager,
for (int j = 0; j < nClusters; ++j) for (int j = 0; j < nClusters; ++j)
{ {
KFbxCluster* pCluster = (KFbxCluster*)pSkin->GetCluster(j); KFbxCluster* pCluster = (KFbxCluster*)pSkin->GetCluster(j);
//assert(KFbxCluster::eNORMALIZE == pCluster->GetLinkMode()); //assert(KFbxCluster::eNORMALIZE == pCluster->GetLinkMode());
KFbxNode* pBone = pCluster->GetLink(); KFbxNode* pBone = pCluster->GetLink();
KFbxXMatrix transformLink; KFbxXMatrix transformLink;
pCluster->GetTransformLinkMatrix(transformLink); pCluster->GetTransformLinkMatrix(transformLink);
KFbxXMatrix transformLinkInverse = transformLink.Inverse(); KFbxXMatrix transformLinkInverse = transformLink.Inverse();
const double* pTransformLinkInverse = transformLinkInverse; const double* pTransformLinkInverse = transformLinkInverse;
if (!boneBindMatrices.insert(std::pair<KFbxNode*, osg::Matrix>(pBone, osg::Matrix(pTransformLinkInverse))).second) 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::notify(osg::WARN) << "Multiple meshes attached to a bone - bind matrices may be incorrect." << std::endl;
} }
int nIndices = pCluster->GetControlPointIndicesCount(); int nIndices = pCluster->GetControlPointIndicesCount();
int* pIndices = pCluster->GetControlPointIndices(); int* pIndices = pCluster->GetControlPointIndices();
@ -555,57 +555,56 @@ osgDB::ReaderWriter::ReadResult readMesh(KFbxSdkManager& pSdkManager,
} }
} }
KFbxXMatrix fbxVertexTransform; KFbxXMatrix fbxGeometricTransform;
fbxVertexTransform.SetTRS( fbxGeometricTransform.SetTRS(
pNode->GeometricTranslation.Get(), pNode->GeometricTranslation.Get(),
pNode->GeometricRotation.Get(), pNode->GeometricRotation.Get(),
pNode->GeometricScaling.Get()); pNode->GeometricScaling.Get());
const double* pVertexMat = fbxVertexTransform; const double* pGeometricMat = fbxGeometricTransform;
osg::Matrix vertexMat(pVertexMat); osg::Matrix osgGeometricTransform(pGeometricMat);
// Bind shape matrix if (geomType == GEOMETRY_RIG)
// For some models this is necessary, however for other models (such as
// those exported from Blender) it shouldn't be applied.
// TODO: Figure out how to make this work in all cases.
KArrayTemplate<KFbxPose*> pPoseList;
KArrayTemplate<int> pIndex;
if (KFbxPose::GetBindPoseContaining(
pSdkManager, pNode, pPoseList, pIndex))
{
const double* pBindShapeMat = pPoseList[0]->GetMatrix(pIndex[0]);
vertexMat.postMult(osg::Matrix(pBindShapeMat));
}
osg::Node* pResult = pGeode;
if (!vertexMat.isIdentity())
{ {
osg::MatrixTransform* pMatTrans = new osg::MatrixTransform(vertexMat); KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN);
pMatTrans->addChild(pGeode); if (pSkin->GetClusterCount())
pResult = pMatTrans; {
KFbxXMatrix fbxTransformMatrix;
pSkin->GetCluster(0)->GetTransformMatrix(fbxTransformMatrix);
const double* pTransformMatrix = fbxTransformMatrix;
osgGeometricTransform.postMult(osg::Matrix(pTransformMatrix));
}
} }
if (geomType == GEOMETRY_RIG) osg::Node* pResult = pGeode;
{
//Add the geometry to the skeleton ancestor of one of the bones.
KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN);
if (pSkin->GetClusterCount())
{
osgAnimation::Skeleton* pSkeleton = getSkeleton(pSkin->GetCluster(0)->GetLink(), skeletonMap);
pSkeleton->addChild(pResult);
return osgDB::ReaderWriter::ReadResult::FILE_LOADED;
}
}
return osgDB::ReaderWriter::ReadResult(pResult); if (!osgGeometricTransform.isIdentity())
{
osg::MatrixTransform* pMatTrans = new osg::MatrixTransform(osgGeometricTransform);
pMatTrans->addChild(pGeode);
pResult = pMatTrans;
}
if (geomType == GEOMETRY_RIG)
{
//Add the geometry to the skeleton ancestor of one of the bones.
KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN);
if (pSkin->GetClusterCount())
{
osgAnimation::Skeleton* pSkeleton = getSkeleton(pSkin->GetCluster(0)->GetLink(), skeletonMap);
pSkeleton->addChild(pResult);
return osgDB::ReaderWriter::ReadResult::FILE_LOADED;
}
}
return osgDB::ReaderWriter::ReadResult(pResult);
} }
osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxSdkManager& pSdkManager, osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxSdkManager& pSdkManager,
KFbxNode* pNode, KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
std::vector<StateSetContent>& stateSetList, std::vector<StateSetContent>& stateSetList,
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices, std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap) std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap)
{ {
KFbxMesh* lMesh = dynamic_cast<KFbxMesh*>(pNode->GetNodeAttribute()); KFbxMesh* lMesh = dynamic_cast<KFbxMesh*>(pNode->GetNodeAttribute());
@ -615,5 +614,5 @@ osgDB::ReaderWriter::ReadResult readFbxMesh(KFbxSdkManager& pSdkManager,
} }
return readMesh(pSdkManager, pNode, lMesh, pAnimationManager, stateSetList, return readMesh(pSdkManager, pNode, lMesh, pAnimationManager, stateSetList,
pNode->GetName(), boneBindMatrices, skeletonMap); pNode->GetName(), boneBindMatrices, skeletonMap);
} }

View File

@ -6,11 +6,11 @@
#include <osg/Material> #include <osg/Material>
#include "fbxMaterialToOsgStateSet.h" #include "fbxMaterialToOsgStateSet.h"
osgDB::ReaderWriter::ReadResult readFbxMesh( osgDB::ReaderWriter::ReadResult readFbxMesh(
FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager, FBXFILESDK_NAMESPACE::KFbxSdkManager& pSdkManager,
FBXFILESDK_NAMESPACE::KFbxNode* pNode, FBXFILESDK_NAMESPACE::KFbxNode* pNode,
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
std::vector<StateSetContent>&, std::vector<StateSetContent>&,
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices, std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap); std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap);
#endif #endif

View File

@ -47,29 +47,29 @@ osg::Quat makeQuat(const fbxDouble3& degrees, ERotationOrder fbxRotOrder)
radiansZ, osg::Vec3d(0,0,1)); radiansZ, osg::Vec3d(0,0,1));
case eEULER_XZY: case eEULER_XZY:
return osg::Quat( return osg::Quat(
radiansX, osg::Vec3d(1,0,0), radiansX, osg::Vec3d(1,0,0),
radiansZ, osg::Vec3d(0,0,1), radiansZ, osg::Vec3d(0,0,1),
radiansY, osg::Vec3d(0,1,0)); radiansY, osg::Vec3d(0,1,0));
case eEULER_YZX: case eEULER_YZX:
return osg::Quat( return osg::Quat(
radiansY, osg::Vec3d(0,1,0), radiansY, osg::Vec3d(0,1,0),
radiansZ, osg::Vec3d(0,0,1), radiansZ, osg::Vec3d(0,0,1),
radiansX, osg::Vec3d(1,0,0)); radiansX, osg::Vec3d(1,0,0));
case eEULER_YXZ: case eEULER_YXZ:
return osg::Quat( return osg::Quat(
radiansY, osg::Vec3d(0,1,0), radiansY, osg::Vec3d(0,1,0),
radiansX, osg::Vec3d(1,0,0), radiansX, osg::Vec3d(1,0,0),
radiansZ, osg::Vec3d(0,0,1)); radiansZ, osg::Vec3d(0,0,1));
case eEULER_ZXY: case eEULER_ZXY:
return osg::Quat( return osg::Quat(
radiansZ, osg::Vec3d(0,0,1), radiansZ, osg::Vec3d(0,0,1),
radiansX, osg::Vec3d(1,0,0), radiansX, osg::Vec3d(1,0,0),
radiansY, osg::Vec3d(0,1,0)); radiansY, osg::Vec3d(0,1,0));
case eEULER_ZYX: case eEULER_ZYX:
return osg::Quat( return osg::Quat(
radiansZ, osg::Vec3d(0,0,1), radiansZ, osg::Vec3d(0,0,1),
radiansY, osg::Vec3d(0,1,0), radiansY, osg::Vec3d(0,1,0),
radiansX, osg::Vec3d(1,0,0)); radiansX, osg::Vec3d(1,0,0));
case eSPHERIC_XYZ: case eSPHERIC_XYZ:
{ {
//I don't know what eSPHERIC_XYZ means, so this is a complete guess. //I don't know what eSPHERIC_XYZ means, so this is a complete guess.
@ -104,7 +104,11 @@ void makeLocalMatrix(const KFbxNode* pNode, osg::Matrix& m)
ScalingPivotInverse: inverse of ScalingPivot ScalingPivotInverse: inverse of ScalingPivot
*/ */
ERotationOrder fbxRotOrder = pNode->RotationOrder.Get(); // When this flag is set to false, the RotationOrder, the Pre/Post rotation
// values and the rotation limits should be ignored.
bool rotationActive = pNode->RotationActive.Get();
ERotationOrder fbxRotOrder = rotationActive ? pNode->RotationOrder.Get() : eEULER_XYZ;
fbxDouble3 fbxLclPos = pNode->LclTranslation.Get(); fbxDouble3 fbxLclPos = pNode->LclTranslation.Get();
fbxDouble3 fbxRotOff = pNode->RotationOffset.Get(); fbxDouble3 fbxRotOff = pNode->RotationOffset.Get();
@ -120,10 +124,17 @@ void makeLocalMatrix(const KFbxNode* pNode, osg::Matrix& m)
fbxLclPos[0] + fbxRotOff[0] + fbxRotPiv[0], fbxLclPos[0] + fbxRotOff[0] + fbxRotPiv[0],
fbxLclPos[1] + fbxRotOff[1] + fbxRotPiv[1], fbxLclPos[1] + fbxRotOff[1] + fbxRotPiv[1],
fbxLclPos[2] + fbxRotOff[2] + fbxRotPiv[2])); fbxLclPos[2] + fbxRotOff[2] + fbxRotPiv[2]));
m.preMultRotate( if (rotationActive)
makeQuat(fbxPostRot, fbxRotOrder) * {
makeQuat(fbxLclRot, fbxRotOrder) * m.preMultRotate(
makeQuat(fbxPreRot, fbxRotOrder)); makeQuat(fbxPostRot, fbxRotOrder) *
makeQuat(fbxLclRot, fbxRotOrder) *
makeQuat(fbxPreRot, fbxRotOrder));
}
else
{
m.preMultRotate(makeQuat(fbxLclRot, fbxRotOrder));
}
m.preMultTranslate(osg::Vec3d( m.preMultTranslate(osg::Vec3d(
fbxSclOff[0] + fbxSclPiv[0] - fbxRotPiv[0], fbxSclOff[0] + fbxSclPiv[0] - fbxRotPiv[0],
fbxSclOff[1] + fbxSclPiv[1] - fbxRotPiv[1], fbxSclOff[1] + fbxSclPiv[1] - fbxRotPiv[1],
@ -226,13 +237,24 @@ void readUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform* pUpdate, KFb
fbxRotPiv[1] + fbxRotOffset[1], fbxRotPiv[1] + fbxRotOffset[1],
fbxRotPiv[2] + fbxRotOffset[2])); fbxRotPiv[2] + fbxRotOffset[2]));
ERotationOrder fbxRotOrder = pNode->RotationOrder.IsValid() ? pNode->RotationOrder.Get() : eEULER_XYZ; // When this flag is set to false, the RotationOrder, the Pre/Post rotation
// values and the rotation limits should be ignored.
bool rotationActive = pNode->RotationActive.Get();
staticTransform.preMultRotate(makeQuat(pNode->PreRotation.Get(), fbxRotOrder)); ERotationOrder fbxRotOrder = (rotationActive && pNode->RotationOrder.IsValid()) ?
pNode->RotationOrder.Get() : eEULER_XYZ;
if (rotationActive)
{
staticTransform.preMultRotate(makeQuat(pNode->PreRotation.Get(), fbxRotOrder));
}
readRotationElement(pNode->LclRotation, fbxRotOrder, pUpdate, staticTransform); readRotationElement(pNode->LclRotation, fbxRotOrder, pUpdate, staticTransform);
staticTransform.preMultRotate(makeQuat(pNode->PostRotation.Get(), fbxRotOrder)); if (rotationActive)
{
staticTransform.preMultRotate(makeQuat(pNode->PostRotation.Get(), fbxRotOrder));
}
fbxDouble3 fbxSclOffset = pNode->ScalingOffset.Get(); fbxDouble3 fbxSclOffset = pNode->ScalingOffset.Get();
fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get(); fbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get();
@ -256,7 +278,7 @@ void readUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform* pUpdate, KFb
osg::Group* createGroupNode(KFbxSdkManager& pSdkManager, KFbxNode* pNode, osg::Group* createGroupNode(KFbxSdkManager& pSdkManager, KFbxNode* pNode,
const std::string& animName, const osg::Matrix& localMatrix, bool bNeedSkeleton, const std::string& animName, const osg::Matrix& localMatrix, bool bNeedSkeleton,
std::map<KFbxNode*, osg::Node*>& nodeMap) std::map<KFbxNode*, osg::Node*>& nodeMap)
{ {
if (bNeedSkeleton) if (bNeedSkeleton)
{ {
@ -267,7 +289,7 @@ osg::Group* createGroupNode(KFbxSdkManager& pSdkManager, KFbxNode* pNode,
readUpdateMatrixTransform(pUpdate, pNode); readUpdateMatrixTransform(pUpdate, pNode);
osgBone->setUpdateCallback(pUpdate); osgBone->setUpdateCallback(pUpdate);
nodeMap.insert(std::pair<KFbxNode*, osg::Node*>(pNode, osgBone)); nodeMap.insert(std::pair<KFbxNode*, osg::Node*>(pNode, osgBone));
return osgBone; return osgBone;
} }
@ -300,9 +322,9 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
bool& bIsBone, int& nLightCount, bool& bIsBone, int& nLightCount,
FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet,
std::map<KFbxNode*, osg::Node*>& nodeMap, std::map<KFbxNode*, osg::Node*>& nodeMap,
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices, std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap, std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap,
const osgDB::Options* options) const osgDB::Options* options)
{ {
if (KFbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute()) if (KFbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute())
@ -315,8 +337,8 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
} }
} }
bIsBone = false; bIsBone = false;
bool bCreateSkeleton = false; bool bCreateSkeleton = false;
KFbxNodeAttribute::EAttributeType lAttributeType = KFbxNodeAttribute::eUNIDENTIFIED; KFbxNodeAttribute::EAttributeType lAttributeType = KFbxNodeAttribute::eUNIDENTIFIED;
if (pNode->GetNodeAttribute()) if (pNode->GetNodeAttribute())
@ -355,7 +377,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
osgDB::ReaderWriter::ReadResult childResult = readFbxNode( osgDB::ReaderWriter::ReadResult childResult = readFbxNode(
pSdkManager, pChildNode, pAnimationManager, pSdkManager, pChildNode, pAnimationManager,
bChildIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap, bChildIsBone, nLightCount, fbxMaterialToOsgStateSet, nodeMap,
boneBindMatrices, skeletonMap, options); boneBindMatrices, skeletonMap, options);
if (childResult.error()) if (childResult.error())
{ {
return childResult; return childResult;
@ -364,7 +386,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
{ {
if (bChildIsBone) if (bChildIsBone)
{ {
if (!bIsBone) bCreateSkeleton = true; if (!bIsBone) bCreateSkeleton = true;
skeletal.push_back(osgChild); skeletal.push_back(osgChild);
} }
else else
@ -401,23 +423,23 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
break; break;
case KFbxNodeAttribute::eMESH: case KFbxNodeAttribute::eMESH:
{ {
size_t bindMatrixCount = boneBindMatrices.size(); size_t bindMatrixCount = boneBindMatrices.size();
osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pSdkManager, osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pSdkManager,
pNode, pAnimationManager, stateSetList, boneBindMatrices, skeletonMap); pNode, pAnimationManager, stateSetList, boneBindMatrices, skeletonMap);
if (meshRes.error()) if (meshRes.error())
{ {
return meshRes; return meshRes;
} }
else if (osg::Node* node = meshRes.getNode()) else if (osg::Node* node = meshRes.getNode())
{ {
bEmpty = false; bEmpty = false;
if (bindMatrixCount != boneBindMatrices.size()) if (bindMatrixCount != boneBindMatrices.size())
{ {
//The mesh is skinned therefore the bind matrix will handle all transformations. //The mesh is skinned therefore the bind matrix will handle all transformations.
localMatrix.makeIdentity(); localMatrix.makeIdentity();
bLocalMatrixIdentity = true; bLocalMatrixIdentity = true;
} }
if (animName.empty() && if (animName.empty() &&
children.empty() && children.empty() &&
@ -427,7 +449,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
return osgDB::ReaderWriter::ReadResult(node); return osgDB::ReaderWriter::ReadResult(node);
} }
children.insert(children.begin(), node); children.insert(children.begin(), node);
} }
} }
break; break;
@ -451,7 +473,7 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
} }
else else
{ {
children.insert(children.begin(), resGroup); children.insert(children.begin(), resGroup);
} }
} }
} }
@ -465,14 +487,14 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
if (!osgGroup) osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bIsBone, nodeMap); if (!osgGroup) osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bIsBone, nodeMap);
osg::Group* pAddChildrenTo = osgGroup.get(); osg::Group* pAddChildrenTo = osgGroup.get();
if (bCreateSkeleton) if (bCreateSkeleton)
{ {
osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, skeletonMap); osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, skeletonMap);
osgSkeleton->setDefaultUpdateCallback(); osgSkeleton->setDefaultUpdateCallback();
pAddChildrenTo->addChild(osgSkeleton); pAddChildrenTo->addChild(osgSkeleton);
pAddChildrenTo = osgSkeleton; pAddChildrenTo = osgSkeleton;
} }
for (osg::NodeList::iterator it = skeletal.begin(); it != skeletal.end(); ++it) for (osg::NodeList::iterator it = skeletal.begin(); it != skeletal.end(); ++it)
{ {
@ -488,26 +510,26 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
} }
osgAnimation::Skeleton* getSkeleton(KFbxNode* fbxNode, osgAnimation::Skeleton* getSkeleton(KFbxNode* fbxNode,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap) std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap)
{ {
//Find the first non-skeleton ancestor of the node. //Find the first non-skeleton ancestor of the node.
while (fbxNode && while (fbxNode &&
fbxNode->GetNodeAttribute() && fbxNode->GetNodeAttribute() &&
fbxNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eSKELETON) fbxNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eSKELETON)
{ {
fbxNode = fbxNode->GetParent(); fbxNode = fbxNode->GetParent();
} }
std::map<KFbxNode*, osgAnimation::Skeleton*>::const_iterator it = skeletonMap.find(fbxNode); std::map<KFbxNode*, osgAnimation::Skeleton*>::const_iterator it = skeletonMap.find(fbxNode);
if (it == skeletonMap.end()) if (it == skeletonMap.end())
{ {
osgAnimation::Skeleton* skel = new osgAnimation::Skeleton; osgAnimation::Skeleton* skel = new osgAnimation::Skeleton;
skel->setDefaultUpdateCallback(); skel->setDefaultUpdateCallback();
skeletonMap.insert(std::pair<KFbxNode*, osgAnimation::Skeleton*>(fbxNode, skel)); skeletonMap.insert(std::pair<KFbxNode*, osgAnimation::Skeleton*>(fbxNode, skel));
return skel; return skel;
} }
else else
{ {
return it->second; return it->second;
} }
} }

View File

@ -16,9 +16,9 @@ osgDB::ReaderWriter::ReadResult readFbxNode(
bool& bIsBone, bool& bIsBone,
int& nLightCount, int& nLightCount,
FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet, FbxMaterialToOsgStateSet& fbxMaterialToOsgStateSet,
std::map<KFbxNode*, osg::Node*>& nodeMap, std::map<KFbxNode*, osg::Node*>& nodeMap,
std::map<KFbxNode*, osg::Matrix>& boneBindMatrices, std::map<KFbxNode*, osg::Matrix>& boneBindMatrices,
std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap, std::map<KFbxNode*, osgAnimation::Skeleton*>& skeletonMap,
const osgDB::Options* options = NULL); const osgDB::Options* options = NULL);
#endif #endif