In supplemental to Syntac_'s example, here's how you could also load some keyframe and skeletal animation data.
For a start, given you have an Fbx scene object initialized, you could pass fbxScene->GetRootNode() to a method like this:
void MyFbxScene::LoadNode(FbxNode* fbxNode)
{
int numAttributes = fbxNode->GetNodeAttributeCount();
for (int i = 0; i < numAttributes; i++)
{
FbxNodeAttribute *nodeAttributeFbx = fbxNode->GetNodeAttributeByIndex(i);
FbxNodeAttribute::EType attributeType = nodeAttributeFbx->GetAttributeType();
switch (attributeType)
{
case FbxNodeAttribute::eMesh:
{
// Load keyframe transformations
this->LoadNodeKeyframeAnimation(fbxNode);
// Load mesh vertices, texcoords, normals, etc
this->LoadMesh((FbxMesh*)nodeAttributeFbx);
// Load mesh skeleton
this->LoadMesh_Skeleton((FbxMesh*)nodeAttributeFbx);
break;
}
}
}
// Load the child nodes
int numChildren = fbxNode->GetChildCount();
for(int i = 0; i < numChildren; i++)
{
this->LoadNode(fbxNode->GetChild(i));
}
}
Load some mesh data
void MyFbxScene::LoadMesh(FbxMesh *fbxMesh)
// Load Vertices
int numVertices = fbxMesh->GetControlPointsCount();
FbxVector4 *verticesFbx = fbxMesh->GetControlPoints();
for (int vertexIndex = 0; vertexIndex < numVertices; vertexIndex++)
{
float x = (float)verticesFbx[vertexIndex][0];
float y = (float)verticesFbx[vertexIndex][0];
float z = (float)verticesFbx[vertexIndex][0];
}
// You'd probably want to also load at least texture coords. It's a little bit complicated, if you want to take into account the different mapping modes, but you can check it from the reference link i've included below
// You may also want to load normals, as Syntac_ suggests, as well as tangents, or you could generate them yourself. And you could load any bone weights if you want to perform skinning animation.
}
Load keyframes - the data on translation, rotation and scaling for each keyframe of an animation
void MyFbxScene::LoadNodeKeyframeAnimation(FbxNode* fbxNode)
{
bool isAnimated = false;
// Iterate all animations (for example, walking, running, falling and etc.)
int numAnimations = this->fbxScene->GetSrcObjectCount(FbxAnimStack::ClassId);
for (int animationIndex = 0; animationIndex < numAnimations; animationIndex++)
{
FbxAnimStack *animStack = (FbxAnimStack*)this->fbxScene->GetSrcObject(FbxAnimStack::ClassId, animationIndex);
FbxAnimEvaluator *animEvaluator = this->fbxScene->GetAnimationEvaluator();
animStack->GetName(); // Get the name of the animation if needed
// Iterate all the transformation layers of the animation. You can have several layers, for example one for translation, one for rotation, one for scaling and each can have keys at different frame numbers.
int numLayers = animStack->GetMemberCount();
for (int layerIndex = 0; layerIndex < numLayers; layerIndex++)
{
FbxAnimLayer *animLayer = (FbxAnimLayer*)animStack->GetMember(layerIndex);
animLayer->GetName(); // Get the layer's name if needed
FbxAnimCurve *translationCurve = fbxNode->LclTranslation.GetCurve(animLayer);
FbxAnimCurve *rotationCurve = fbxNode->LclRotation.GetCurve(animLayer);
FbxAnimCurve *scalingCurve = fbxNode->LclScaling.GetCurve(animLayer);
if (scalingCurve != 0)
{
int numKeys = scalingCurve->KeyGetCount();
for (int keyIndex = 0; keyIndex < numKeys; keyIndex++)
{
FbxTime frameTime = scalingCurve->KeyGetTime(keyIndex);
FbxDouble3 scalingVector = fbxNode->EvaluateLocalScaling(frameTime);
float x = (float)scalingVector[0];
float y = (float)scalingVector[1];
float z = (float)scalingVector[2];
float frameSeconds = (float)frameTime.GetSecondDouble(); // If needed, get the time of the scaling keyframe, in seconds
}
}
else
{
// If this animation layer has no scaling curve, then use the default one, if needed
FbxDouble3 scalingVector = fbxNode->LclScaling.Get();
float x = (float)scalingVector[0];
float y = (float)scalingVector[1];
float z = (float)scalingVector[2];
}
// Analogically, process rotationa and translation
}
}
}
Load skeletal animation
void MyFbxScene::LoadMesh_Skeleton(FbxMesh *fbxMesh)
{
int numDeformers = fbxMesh->GetDeformerCount();
FbxSkin* skin = (FbxSkin*)fbxMesh->GetDeformer(0, FbxDeformer::eSkin);
if (skin != 0)
{
int boneCount = skin->GetClusterCount();
for (int boneIndex = 0; boneIndex < boneCount; boneIndex++)
{
FbxCluster* cluster = skin->GetCluster(boneIndex);
FbxNode* bone = cluster->GetLink(); // Get a reference to the bone's node
// Get the bind pose
FbxAMatrix bindPoseMatrix;
cluster->GetTransformLinkMatrix(bindPoseMatrix);
int *boneVertexIndices = cluster->GetControlPointIndices();
double *boneVertexWeights = cluster->GetControlPointWeights();
// Iterate through all the vertices, which are affected by the bone
int numBoneVertexIndices = cluster->GetControlPointIndicesCount();
for (int boneVertexIndex = 0; boneVertexIndex < numBoneVertexIndices; boneVertexIndex++)
{
int boneVertexIndex = boneVertexIndices[boneVertexIndex];
float boneWeight = (float)boneVertexWeights[boneVertexIndex];
}
}
}
}
However, it's a bit complicated, because if you want to open the fbx properly, you'd have to consider things like smoothing groups and sub materials. Skinning is also tricky, because of taking the mesh's binding pose and the pile of tranformations affecting the mesh. It's kinda messy.
These examples are adapted cut-offs from Meshwork's MwModuleFbx. For a complete example reference, you can take a look at the full code, but bear in mind that it too has issues with skinning.
You can find it at http://morroworks.com/meshwork/source/