std::string readFbxAnimation(KFbxNode* pNode, KFbxScene& fbxScene, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager, const char* targetName) { std::string result; for (int i = 0; i < fbxScene.GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); ++i) { KFbxAnimStack* pAnimStack = KFbxCast<KFbxAnimStack>(fbxScene.GetSrcObject(FBX_TYPE(KFbxAnimStack), i)); int nbAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer)); const char* pTakeName = pAnimStack->GetName(); if (!pTakeName || !*pTakeName) continue; for (int j = 0; j < nbAnimLayers; j++) { KFbxAnimLayer* pAnimLayer = pAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), j); if (osgAnimation::Animation* pAnimation = readFbxAnimation( pNode, pAnimLayer, pTakeName, targetName, pAnimManager)) { result = targetName; } } } return result; }
void readAnimation(KFbxNode* pNode, KFbxScene& fbxScene, const std::string& targetName, osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager, KFbxMesh* pMesh, int nBlendShape, int nBlendShapeChannel, int nShape) { for (int i = 0; i < fbxScene.GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); ++i) { KFbxAnimStack* pAnimStack = KFbxCast<KFbxAnimStack>(fbxScene.GetSrcObject(FBX_TYPE(KFbxAnimStack), i)); int nbAnimLayers = pAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer)); const char* pTakeName = pAnimStack->GetName(); if (!pTakeName || !*pTakeName) continue; for (int j = 0; j < nbAnimLayers; j++) { KFbxAnimLayer* pAnimLayer = pAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), j); KFbxAnimCurve* pCurve = pMesh->GetShapeChannel(nBlendShape, nBlendShapeChannel, pAnimLayer, false); if (!pCurve) { continue; } int nKeys = pCurve->KeyGetCount(); if (!nKeys) { continue; } osgAnimation::FloatLinearChannel* pChannel = new osgAnimation::FloatLinearChannel; std::vector<osgAnimation::TemplateKeyframe<float> >& keyFrameCntr = *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer(); for (int k = 0; k < nKeys; ++k) { KFbxAnimCurveKey key = pCurve->KeyGet(k); double fTime = key.GetTime().GetSecondDouble(); float fValue = static_cast<float>(key.GetValue() * 0.01); keyFrameCntr.push_back(osgAnimation::FloatKeyframe(fTime,fValue)); } pChannel->setTargetName(targetName); std::stringstream ss; ss << nShape; pChannel->setName(ss.str()); addChannel(pChannel, pAnimationManager, pTakeName); } } }
void FBXModel::load(const GraphicsDevice& device, const std::string& filename, unsigned keyframes) { if (effect.resource == 0) effect = Effect::createFromFile<FBXEffect>(device, Config::getValue(ConfigKeys::fbxEffectPath)); defaultTexture = Texture::createFromFile(device, defaultTexturePath); vertexDeclaration = device.createVertexDeclaration(FBXInstance::vertexElements); KFbxSdkManager* sdkManager = KFbxSdkManager::Create(); KFbxIOSettings* ios = KFbxIOSettings::Create(sdkManager, IOSROOT); sdkManager->SetIOSettings(ios); // Create an importer using our sdk manager. KFbxImporter* importer = KFbxImporter::Create(sdkManager, ""); importer->Initialize(filename.c_str(), -1, sdkManager->GetIOSettings()); // Create a new scene so it can be populated by the imported file. KFbxScene* scene = KFbxScene::Create(sdkManager, ""); // Import the contents of the file into the scene. importer->Import(scene); KFbxNode* rootBone = 0; KFbxNode* rootNode = scene->GetRootNode(); KFbxAnimStack* animStack = KFbxCast<KFbxAnimStack>(scene->GetSrcObject(FBX_TYPE(KFbxAnimStack), 0)); KFbxAnimLayer* animLayer = 0; if (animStack) { animLayer = animStack->GetMember(FBX_TYPE(KFbxAnimLayer), 0); scene->GetEvaluator()->SetContext(animStack); } loadBones(rootNode, &rootBone, animLayer); loadMeshes(rootNode, device, KFbxGeometryConverter(sdkManager)); if (animLayer) { for (unsigned i = 0; i <= keyframes; ++i) boneMatricesMap[i] = traverseBones(i, rootBone, Matrix::identity, MatrixCollection(bones.size())); } sdkManager->Destroy(); loaded = true; }
// -- Actions ---------------------------------------------------------------- void Scene::setAnimation(int index) { LOG_INFO( "Scene::setAnimation("<< index <<")"); int numAnimStacks = animationNames.GetCount(); if (!numAnimStacks || index >= numAnimStacks) { return; } // select the base layer from the animation stack KFbxAnimStack* currentAnimationStack = fbxScene->FindMember(FBX_TYPE(KFbxAnimStack), animationNames[index]->Buffer()); if (currentAnimationStack == NULL) { // this is a problem. The anim stack should be found in the scene! LOG_INFO( "The anim stack should be found in the scene!\n"); return; } // we assume that the first animation layer connected to the animation stack is the base layer // (this is the assumption made in the FBXSDK) currentAnimationLayer = currentAnimationStack->GetMember(FBX_TYPE(KFbxAnimLayer), 0); fbxScene->GetEvaluator()->SetContext(currentAnimationStack); KFbxTakeInfo* lCurrentTakeInfo = fbxScene->GetTakeInfo(*(animationNames[index])); if (lCurrentTakeInfo) { start = lCurrentTakeInfo->mLocalTimeSpan.GetStart(); stop = lCurrentTakeInfo->mLocalTimeSpan.GetStop(); printf("Scene::initAnimStack $1 start %f stop %f \n", start.GetSecondDouble(), stop.GetSecondDouble()); } else { // Take the time line value KTimeSpan lTimeLineTimeSpan; fbxScene->GetGlobalSettings().GetTimelineDefaultTimeSpan(lTimeLineTimeSpan); start = lTimeLineTimeSpan.GetStart(); stop = lTimeLineTimeSpan.GetStop(); printf("Scene::initAnimStack $2 start %f stop %f \n", start.GetSecondDouble(), stop.GetSecondDouble()); } currentTime = start; }