Hi, fellow devs, I've successfully loaded 3d models from fbx files. The only problem I face is constructing vertex structure with skeletal data(bone ids and weights) from the model. I know how to retrieve those data from fbx. Here's my code for above process.
Mesh FBXCLoader::ProcessMesh(ID3D11Device * dev, ID3D11DeviceContext *devcon, FbxMesh * mesh)
std::vector<VERTEX> meshvertices;
ID3D11ShaderResourceView *meshtexture = nullptr;
FbxVector4 *vertices = mesh->GetControlPoints();
for (int j = 0; j < mesh->GetPolygonCount(); j++)
int numVertices = mesh->GetPolygonSize(j);
FbxLayerElementArrayTemplate<FbxVector2> *uvVertices = 0;
mesh->GetTextureUV(&uvVertices, FbxLayerElement::eTextureDiffuse);
for (int k = 0; k < numVertices; k++)
int controlPointIndex = mesh->GetPolygonVertex(j, k);
VERTEX vertex;
vertex.pos.x = (float)vertices[controlPointIndex].mData[0];
vertex.pos.y = (float)vertices[controlPointIndex].mData[1];
vertex.pos.z = (float)vertices[controlPointIndex].mData[2];
vertex.tex.x = (float)uvVertices->GetAt(mesh->GetTextureUVIndex(j, k)).mData[0];
vertex.tex.y = 1.0f - (float)uvVertices->GetAt(mesh->GetTextureUVIndex(j, k)).mData[1];
controlpoints[controlPointIndex] = (int)meshvertices.size();
meshvertices.push_back(vertex);
int materialcount = mesh->GetNode()->GetSrcObjectCount<FbxSurfaceMaterial>();
for (int i = 0; i < materialcount; i++)
FbxSurfaceMaterial *material = (FbxSurfaceMaterial*)mesh->GetNode()->GetSrcObject<FbxSurfaceMaterial>(i);
if (material)
FbxProperty prop = material->FindProperty(FbxSurfaceMaterial::sDiffuse);
const FbxTexture* texture = FbxCast<FbxTexture>(prop.GetSrcObject<FbxTexture>(0));
const FbxFileTexture* filetexture = FbxCast<FbxFileTexture>(texture);
ID3D11ShaderResourceView *meshctexture = LoadTexture(dev, devcon, filetexture->GetFileName());
meshtexture = meshctexture;
const FbxVector4 lT = mesh->GetNode()->GetGeometricTranslation(FbxNode::eSourcePivot);
const FbxVector4 lR = mesh->GetNode()->GetGeometricRotation(FbxNode::eSourcePivot);
const FbxVector4 lS = mesh->GetNode()->GetGeometricScaling(FbxNode::eSourcePivot);
FbxAMatrix geometryTransform = FbxAMatrix(lT, lR, lS);
for (unsigned int deformerIndex = 0; deformerIndex < (UINT)mesh->GetDeformerCount(); ++deformerIndex)
FbxSkin* skin = reinterpret_cast<FbxSkin*>(mesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
if (!skin)
continue;
for (unsigned int clusterIndex = 0; clusterIndex < (UINT)skin->GetClusterCount(); ++clusterIndex)
FbxCluster* cluster = skin->GetCluster(clusterIndex);
std::string jointname = cluster->GetLink()->GetName();
unsigned int jointIndex = FindJointIndex(jointname);
FbxAMatrix transformMatrix;
FbxAMatrix transformLinkMatrix;
FbxAMatrix globalBindposeInverseMatrix;
cluster->GetTransformMatrix(transformMatrix);
cluster->GetTransformLinkMatrix(transformLinkMatrix);
globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;
skeleton.mJoints[jointIndex].mGlobalBindposeInverse = globalBindposeInverseMatrix;
skeleton.mJoints[jointIndex].mNode = cluster->GetLink();
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 vertexid = controlpoints[boneVertexIndices[boneVertexIndex]];
meshvertices[vertexid].boneids.x = jointIndex;
meshvertices[vertexid].boneids.y = jointIndex;
meshvertices[vertexid].boneids.z = jointIndex;
meshvertices[vertexid].boneids.w = jointIndex;
meshvertices[vertexid].weights.x = (float)boneVertexWeights[boneVertexIndex];
meshvertices[vertexid].weights.y = (float)boneVertexWeights[boneVertexIndex];
meshvertices[vertexid].weights.z = (float)boneVertexWeights[boneVertexIndex];
meshvertices[vertexid].weights.w = (float)boneVertexWeights[boneVertexIndex];
FbxAnimStack* animstack = fbxScene->GetSrcObject<FbxAnimStack>(0);
FbxString animstackname = animstack->GetName();
FbxTakeInfo* takeinfo = fbxScene->GetTakeInfo(animstackname);
FbxTime start = takeinfo->mLocalTimeSpan.GetStart();
FbxTime end = takeinfo->mLocalTimeSpan.GetStop();
FbxLongLong animationlength = end.GetFrameCount(FbxTime::eFrames30) - start.GetFrameCount(FbxTime::eFrames30) + 1;
Keyframe** anim = &skeleton.mJoints[jointIndex].mAnimation;
for (FbxLongLong i = start.GetFrameCount(FbxTime::eFrames30); i <= end.GetFrameCount(FbxTime::eFrames30); ++i)
FbxTime time;
time.SetFrame(i, FbxTime::eFrames30);
*anim = new Keyframe();
(*anim)->mFrameNum = i;
FbxAMatrix transformoffset = mesh->GetNode()->EvaluateGlobalTransform(1.0) * geometryTransform;
(*anim)->mGlobalTransform = transformoffset.Inverse() * cluster->GetLink()->EvaluateGlobalTransform(time);
anim = &((*anim)->mNext);
return Mesh(dev, meshvertices, meshtexture);