相关文章推荐

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);



FBXLOADER.H
class FBXCLoader
public:
    FBXCLoader(void);
    ~FBXCLoader(void);
    void LoadFBX(HWND hwnd, ID3D11Device *dev, ID3D11DeviceContext *devcon, const char* filename);
    void Draw(ID3D11DeviceContext *devcon);
    XMMATRIX GetAnimatedMatrix(int index);
    Skeleton skeleton;
private:
    FbxManager *fbxsdkManager;
    FbxScene *fbxScene;
    std::map<int, int> controlpoints;
    std::vector<Mesh> meshes;
    HWND hwnd;
    void ProcessNode(ID3D11Device *dev, ID3D11DeviceContext *devcon, FbxNode *node, FbxGeometryConverter *gConverter);
    Mesh ProcessMesh(ID3D11Device* dev, ID3D11DeviceContext *devcon, FbxMesh *mesh);
    void ProcessSkeletonHeirarchy(FbxNode* rootnode);
    void ProcessSkeletonHeirarchyre(FbxNode* node, int depth, int index, int parentindex);
    unsigned int FindJointIndex(const std::string& jointname);
    ID3D11ShaderResourceView *LoadTexture(ID3D11Device *dev, ID3D11DeviceContext *devcon, const char* texturefilename);
            
            

My article might have useful info, it was years ago I wrote it though and for .x format

https://www.gamedev.net/tutorials/programming/graphics/animating-characters-with-directx-r3632/

 
推荐文章