To render (i.e., display) a scene containing animation, you need to evaluate at many points in time the animated properties of the relevant objects in the scene. For example, if you want to show a moving racecar, and the racecar is represented by a mesh, you must animate the local translation property of the node whose node attribute is the mesh. (see KFbxNode::LclTranslation).
Start by getting an evaluator object from the scene object that contains the node:
// Let’s assume that myScene has been created already KFbxAnimEvaluator* mySceneEvaluator = MyScene->GetEvaluator();
KTime myTime; // The time for each key in the animation curve(s) myTime.SetSecondDouble(0.0); // Starting time
// Create a node object KFbxNode* myMeshNode = KFbxNode::Create (myScene, ""); ... // Code to connect myMeshNode to a mesh object
Then you can get the global transformation matrix of the relevant node at the specified time:
// Get a reference to node’s global transform. KFbxXMatrix& GlobalMatrix = mySceneEvaluator->GetNodeGlobalTransform(myMeshNode, myTime);
Or, if you prefer, the node’s local transformation matrix at the specified time:
// Get a reference to node’s local transform. KFbxXMatrix& GlobalMatrix = mySceneEvaluator->GetNodeLocalTransform(myMeshNode, myTime);
To animate a camera, you don’t need a transformation matrix. All you need is the camera’s position, expressed as a vector, at the specified time:
// Given a scene, we can create a camera KFbxCamera* myCamera = KFbxCamera::Create (myScene, ""); // Store the value of the property... in an animation curve node!? KFbxAnimCurveNode& myCameraPositionVector; // Get and store the value of the camera's local translation myCameraPositionVector = mySceneEvaluator->GetPropertyValue (myCamera->Position, myTime);
We are not using the KFbxAnimCurveNode object for its normal purpose, that is, we are not using it as a connection point between an animation curve and an FBX property.
We are using an animation curve node as a convenient place to store the vector of the property returned by the evaluator. That’s because the animatable properties of FBX objects come in many data types. Some data types are for scalars; examples include fbxDouble1, fbxInteger1, and fbxBool1. Other data types have values that are (X, Y, Z) triplets that are stored as vectors.
In our code snippet above, KFbxNode::LclTranslation is of type fbxDouble3, a vector with three elements. KFbxAnimCurveNode is a container that can store the value of any FBX property no matter what its type. And KFbxAnimCurveNode’s member functions allow you to access the value of each element in a vector by, in this case, getting the value of a channel X, the value of channel Y, and the value of channel Z.
Resolving gimbal locks using unroll filters
The KFbxKFCurveFilterUnroll class is used to create an unroll filter to remove gimbal locks. Such a filter requires three rotation curves in the same Apply() call. This filter expects to work with interdependent curves. The curves are expected to be in the X, Y, Z order regardless of the node's rotation order. The rotation curves are unrolled with priority on the Y-axis, or whichever curve is in the second position. The following snippet illustrates the use of unroll filters in the FBX SDK.
KFbxKFCurveFilterUnroll *lUnroller = KFbxKFCurveFilterUnroll::Create(pSdkManager, ""); KFbxAnimCurve* lCurve[3]; lCurve[0] = lRotationCurveX; lCurve[1] = lRotationCurveY; lCurve[2] = lRotationCurveZ; lUnroller->Reset(); lUnroller->Apply((KFbxAnimCurve**)lCurve, 3);