C++ FBX Animation Importer Using the FBX SDK
- by Mike Sawayda
Does anyone have any experience using the FBX SDK to load in animations. I got the meshes loaded in correctly with all of their verts, indices, UV's, and normals. I am just now trying to get the Animations working correctly. I have looked at the FBX SDK documentation with little help. If someone could just help me get started or point me in the right direction I would greatly appreciate it. I added some code so you can kinda get an idea of what I am doing. I should be able to place that code anywhere in the load FBX function and have it work.
//GETTING ANIMAION DATA
for(int i = 0; i < scene->GetSrcObjectCount<FbxAnimStack>(); ++i)
{
FbxAnimStack* lAnimStack = scene->GetSrcObject<FbxAnimStack>(i);
FbxString stackName = "Animation Stack Name: ";
stackName += lAnimStack->GetName();
string sStackName = stackName;
int numLayers = lAnimStack->GetMemberCount<FbxAnimLayer>();
for(int j = 0; j < numLayers; ++j)
{
FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(j);
FbxString layerName = "Animation Stack Name: ";
layerName += lAnimLayer->GetName();
string sLayerName = layerName;
queue<FbxNode*> nodes;
FbxNode* tempNode = scene->GetRootNode();
while(tempNode != NULL)
{
FbxAnimCurve* lAnimCurve = tempNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
if(lAnimCurve != NULL)
{
//I know something needs to be done here but I dont know what.
}
for(int i = 0; i < tempNode->GetChildCount(false); ++i)
{
nodes.push(tempNode->GetChild(i));
}
if(nodes.size() > 0)
{
tempNode = nodes.front();
nodes.pop();
}
else
{
tempNode = NULL;
}
}
}
}
Here is the full function
bool FBXLoader::LoadFBX(ParentMeshObject* _parentMesh, char* _filePath, bool _hasTexture)
{
FbxManager* fbxManager = FbxManager::Create();
if(!fbxManager)
{
printf( "ERROR %s : %d failed creating FBX Manager!\n", __FILE__, __LINE__ );
}
FbxIOSettings* ioSettings = FbxIOSettings::Create(fbxManager, IOSROOT);
fbxManager->SetIOSettings(ioSettings);
FbxString filePath = FbxGetApplicationDirectory();
fbxManager->LoadPluginsDirectory(filePath.Buffer());
FbxScene* scene = FbxScene::Create(fbxManager, "");
int fileMinor, fileRevision;
int sdkMajor, sdkMinor, sdkRevision;
int fileFormat;
FbxManager::GetFileFormatVersion(sdkMajor, sdkMinor, sdkRevision);
FbxImporter* importer = FbxImporter::Create(fbxManager, "");
if(!fbxManager->GetIOPluginRegistry()->DetectReaderFileFormat(_filePath, fileFormat))
{
//Unrecognizable file format. Try to fall back on FbxImorter::eFBX_BINARY
fileFormat = fbxManager->GetIOPluginRegistry()->FindReaderIDByDescription("FBX binary (*.fbx)");
}
bool importStatus = importer->Initialize(_filePath, fileFormat, fbxManager->GetIOSettings());
importer->GetFileVersion(fileMinor, fileMinor, fileRevision);
if(!importStatus)
{
printf( "ERROR %s : %d FbxImporter Initialize failed!\n", __FILE__, __LINE__ );
return false;
}
importStatus = importer->Import(scene);
if(!importStatus)
{
printf( "ERROR %s : %d FbxImporter failed to import the file to the scene!\n", __FILE__, __LINE__ );
return false;
}
FbxAxisSystem sceneAxisSystem = scene->GetGlobalSettings().GetAxisSystem();
FbxAxisSystem axisSystem( FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eLeftHanded );
if(sceneAxisSystem != axisSystem)
{
axisSystem.ConvertScene(scene);
}
TriangulateRecursive(scene->GetRootNode());
FbxArray<FbxMesh*> meshes;
FillMeshArray(scene, meshes);
unsigned short vertexCount = 0;
unsigned short triangleCount = 0;
unsigned short faceCount = 0;
unsigned short materialCount = 0;
int numberOfVertices = 0;
for(int i = 0; i < meshes.GetCount(); ++i)
{
numberOfVertices += meshes[i]->GetPolygonVertexCount();
}
Face face;
vector<Face> faces;
int indicesCount = 0;
int ptrMove = 0;
float wValue = 0.0f;
if(!_hasTexture)
{
wValue = 1.0f;
}
for(int i = 0; i < meshes.GetCount(); ++i)
{
int vertexCount = 0;
vertexCount = meshes[i]->GetControlPointsCount();
if(vertexCount == 0)
continue;
VertexType* vertices;
vertices = new VertexType[vertexCount];
int triangleCount = meshes[i]->GetPolygonVertexCount() / 3;
indicesCount = meshes[i]->GetPolygonVertexCount();
FbxVector4* fbxVerts = new FbxVector4[vertexCount];
int arrayIndex = 0;
memcpy(fbxVerts, meshes[i]->GetControlPoints(), vertexCount * sizeof(FbxVector4));
for(int j = 0; j < triangleCount; ++j)
{
int index = 0;
FbxVector4 fbxNorm(0, 0, 0, 0);
FbxVector2 fbxUV(0, 0);
bool texCoordFound = false;
face.indices[0] = index = meshes[i]->GetPolygonVertex(j, 0);
vertices[index].position.x = (float)fbxVerts[index][0];
vertices[index].position.y = (float)fbxVerts[index][1];
vertices[index].position.z = (float)fbxVerts[index][2];
vertices[index].position.w = wValue;
meshes[i]->GetPolygonVertexNormal(j, 0, fbxNorm);
vertices[index].normal.x = (float)fbxNorm[0];
vertices[index].normal.y = (float)fbxNorm[1];
vertices[index].normal.z = (float)fbxNorm[2];
texCoordFound = meshes[i]->GetPolygonVertexUV(j, 0, "map1", fbxUV);
vertices[index].texture.x = (float)fbxUV[0];
vertices[index].texture.y = (float)fbxUV[1];
face.indices[1] = index = meshes[i]->GetPolygonVertex(j, 1);
vertices[index].position.x = (float)fbxVerts[index][0];
vertices[index].position.y = (float)fbxVerts[index][1];
vertices[index].position.z = (float)fbxVerts[index][2];
vertices[index].position.w = wValue;
meshes[i]->GetPolygonVertexNormal(j, 1, fbxNorm);
vertices[index].normal.x = (float)fbxNorm[0];
vertices[index].normal.y = (float)fbxNorm[1];
vertices[index].normal.z = (float)fbxNorm[2];
texCoordFound = meshes[i]->GetPolygonVertexUV(j, 1, "map1", fbxUV);
vertices[index].texture.x = (float)fbxUV[0];
vertices[index].texture.y = (float)fbxUV[1];
face.indices[2] = index = meshes[i]->GetPolygonVertex(j, 2);
vertices[index].position.x = (float)fbxVerts[index][0];
vertices[index].position.y = (float)fbxVerts[index][1];
vertices[index].position.z = (float)fbxVerts[index][2];
vertices[index].position.w = wValue;
meshes[i]->GetPolygonVertexNormal(j, 2, fbxNorm);
vertices[index].normal.x = (float)fbxNorm[0];
vertices[index].normal.y = (float)fbxNorm[1];
vertices[index].normal.z = (float)fbxNorm[2];
texCoordFound = meshes[i]->GetPolygonVertexUV(j, 2, "map1", fbxUV);
vertices[index].texture.x = (float)fbxUV[0];
vertices[index].texture.y = (float)fbxUV[1];
faces.push_back(face);
}
meshes[i]->Destroy();
meshes[i] = NULL;
int indexCount = faces.size() * 3;
unsigned long* indices = new unsigned long[faces.size() * 3];
int indicie = 0;
for(unsigned int i = 0; i < faces.size(); ++i)
{
indices[indicie++] = faces[i].indices[0];
indices[indicie++] = faces[i].indices[1];
indices[indicie++] = faces[i].indices[2];
}
faces.clear();
_parentMesh->AddChild(vertices, indices, vertexCount, indexCount);
}
return true;
}