Use animation data from fbx file to do animation

Started by
3 comments, last by isu diss 3 years, 11 months ago

I know how to read skinning data and animation data from fbx. what i dont know is how to combine those data to do animation. can someone help me? I'm following the article, https://www.gamedev.net/tutorials/_/technical/graphics-programming-and-theory/how-to-work-with-fbx-sdk-r3582/

	inStream << "\t<skeleton count='" << mSkeleton.mJoints.size() << "'>" << std::endl;
	for (unsigned int i = 0; i < mSkeleton.mJoints.size(); ++i)
	{
		inStream << "\t\t<joint id='" << i << "' name='" << mSkeleton.mJoints[i].mName << "' parent='" << mSkeleton.mJoints[i].mParentIndex << "'>\n";
		inStream << "\t\t\t";
		FbxVector4 translation = mSkeleton.mJoints[i].mGlobalBindposeInverse.GetT();
		FbxVector4 rotation = mSkeleton.mJoints[i].mGlobalBindposeInverse.GetR();
		translation.Set(translation.mData[0], translation.mData[1], -translation.mData[2]);
		rotation.Set(-rotation.mData[0], -rotation.mData[1], rotation.mData[2]);
		mSkeleton.mJoints[i].mGlobalBindposeInverse.SetT(translation);
		mSkeleton.mJoints[i].mGlobalBindposeInverse.SetR(rotation);
		FbxMatrix out = mSkeleton.mJoints[i].mGlobalBindposeInverse;

		Utilities::WriteMatrix(inStream, out.Transpose(), true);
		inStream << "\t\t</joint>\n";
	}
	inStream << "\t</skeleton>\n";
	inStream << "\t<animations>\n";
	inStream << "\t\t<animation name='" << mAnimationName << "' length='" << mAnimationLength << "'>\n";
	for (unsigned int i = 0; i < mSkeleton.mJoints.size(); ++i)
	{
		inStream << "\t\t\t" << "<track id = '" << i << "' name='" << mSkeleton.mJoints[i].mName << "'>\n";
		Keyframe* walker = mSkeleton.mJoints[i].mAnimation;
		while(walker)
		{
			inStream << "\t\t\t\t" << "<frame num='" << walker->mFrameNum - 1 << "'>\n";
			inStream << "\t\t\t\t\t";
			FbxVector4 translation = walker->mGlobalTransform.GetT();
			FbxVector4 rotation = walker->mGlobalTransform.GetR();
			translation.Set(translation.mData[0], translation.mData[1], -translation.mData[2]);
			rotation.Set(-rotation.mData[0], -rotation.mData[1], rotation.mData[2]);
			walker->mGlobalTransform.SetT(translation);
			walker->mGlobalTransform.SetR(rotation);
			FbxMatrix out = walker->mGlobalTransform;
			Utilities::WriteMatrix(inStream, out.Transpose(), true);
			inStream << "\t\t\t\t" << "</frame>\n";
			walker = walker->mNext;
		}
		inStream << "\t\t\t" << "</track>\n";
	}
Advertisement

i found the solution by myself

isu diss said:

i found the solution by myself

And what was it? Maybe someone can learn from your experience.

			// Update the information in mSkeleton 
			mSkeleton.mJoints[currJointIndex].mGlobalBindposeInverse = globalBindposeInverseMatrix;
			FbxVector4 translation = mSkeleton.mJoints[currJointIndex].mGlobalBindposeInverse.GetT();
			FbxVector4 rotation = mSkeleton.mJoints[currJointIndex].mGlobalBindposeInverse.GetR();
			translation.Set(translation.mData[0], translation.mData[1], -translation.mData[2]);
			rotation.Set(-rotation.mData[0], -rotation.mData[1], rotation.mData[2]);
			mSkeleton.mJoints[currJointIndex].mGlobalBindposeInverse.SetT(translation);
			mSkeleton.mJoints[currJointIndex].mGlobalBindposeInverse.SetR(rotation);
			fbxToMatrix(mSkeleton.mJoints[currJointIndex].mGlobalBindposeInverse, mSkeleton.mJoints[currJointIndex].offset);
			mSkeleton.mJoints[currJointIndex].mNode = currCluster->GetLink();

above code extracts the bone offset or GlobalBindposeInverse.

void GetNodeLocalTransform(FbxNode* nodePtr,  const FbxTime&amp; fbxTime, XMMATRIX&amp; matrix)
{
   FbxAMatrix fbxMatrix = mFBXScene->GetAnimationEvaluator()->GetNodeLocalTransform(nodePtr, fbxTime);
   FbxVector4 translation = fbxMatrix.GetT();
	FbxVector4 rotation = fbxMatrix.GetR();
	translation.Set(translation.mData[0], translation.mData[1], -translation.mData[2]);
	rotation.Set(-rotation.mData[0], -rotation.mData[1], rotation.mData[2]);
	fbxMatrix.SetT(translation);
	fbxMatrix.SetR(rotation);
   fbxToMatrix(fbxMatrix, matrix);
}

above code extracts the node local transform at (fbx)time ‘fbxTime’.

void BuildRequiredMatrices(FbxTime&amp; fbxFrameTime)
{
   for (unsigned long i = 0; i < mSkeleton.mJoints.size(); ++i)
   {
      GetNodeLocalTransform(mSkeleton.mJoints[i].mNode, fbxFrameTime, mSkeleton.mJoints[i].nodeLocalTransform);
   }
   
   for (auto&amp; bone : mSkeleton.mJoints)
   {
      if (bone.mParentIndex != -1)
      {
         bone.combinedTransform = bone.nodeLocalTransform * mSkeleton.mJoints[bone.mParentIndex].combinedTransform;
      }
      else
      {
         bone.combinedTransform = bone.nodeLocalTransform;
      }
   }

   for (auto&amp; bone : mSkeleton.mJoints)
   {
      bone.boneMatrice = bone.offset * bone.combinedTransform;
   }
}

above code does the necessary transforms . I cant explain everything follow this article https://www.gamedev.net/articles/programming/graphics/skinned-mesh-animation-using-matrices-r3577/​

To render the model

FbxTime fbxFrameTime;
fbxFrameTime.SetMilliSeconds(localAnimationTime);//compute the local anima time using 'mAnimationLength'
BuildRequiredMatrices(fbxFrameTime);


RE_VSCB revscb;
revscb.mWorld = XMMatrixTranspose(XMMatrixIdentity());
revscb.mView = XMMatrixTranspose(cam->mView);
revscb.mProjection = XMMatrixTranspose(cam->mProjection);
revscb.mHasAnimation=mHasAnimation;
for (UINT i = 0; i < mSkeleton.mJoints.size(); ++i)
	revscb.Bones[i] = XMMatrixTranspose(mSkeleton.mJoints[i].boneMatrice);
devcon->UpdateSubresource(RE_VSConstBuf, 0, nullptr, &amp;revscb, 0, 0);

Everything is there in the articlehttps://www.gamedev.net/articles/programming/graphics/how-to-work-with-fbx-sdk-r3582/​

Hope this would help anyone who wants to have animation!!!

This topic is closed to new replies.

Advertisement