将`ozz :: math :: float4x4`和`fbxsdk :: fbxdouble4`转换为`glm :: mat4`以进行GPU蒙皮

有人能解释如何将ozz::math::float4x4转换为glm::mat4,然后再乘以fbxsdk::fbxdouble4吗?

void updateUniformBuffer(const uint32_t &currentImage) {
    static auto startTime = std::chrono::high_resolution_clock::now();
    auto currentTime = std::chrono::high_resolution_clock::now();
    float time = std::chrono::duration<float,std::chrono::seconds::period>(currentTime - startTime).count();

    UniformBufferObject ubo = {};
    ubo.model = glm::rotate(glm::mat4(1.0f),time * glm::radians(30.0f),glm::vec3(0.0f,0.0f,1.0f));

    controller_.Update(animation_,1.0f);

    //  Samples optimized animation at t = animation_time_
    ozz::animation::SamplingJob sampling_job;
    sampling_job.animation = &animation_;
    sampling_job.cache = &cache_;
    sampling_job.ratio = controller_.time_ratio();
    sampling_job.output = make_range(locals_);
    if (!sampling_job.Run()) {
        printf("Sampling Job Failed\n");
        return;
    }

    //  Converts from local space to model space matrices
    ozz::animation::LocalToModelJob ltm_job;
    ltm_job.skeleton = &skeleton_;
    ltm_job.input = make_range(locals_);
    ltm_job.output = make_range(models_);
    if (!ltm_job.Run()) {
        printf("LocalToModel Job Failed\n");
        return;
    }

    auto joints = skeleton_.num_joints();
    printf("UBO Joints %i\n",joints);
    for (int i = 0; i < joints; i++) {

        if (i >= bindPoses.size()) { break; }

        FbxAMatrix InvBind = bindPoses[i].Inverse();

        //  glm_row* == Final Bone Matrix Sent To GPU
        //  ozz_row* == Bone Matrix After Animation
        //  fbx_row* == Bone Inverse Bind Pose

        glm::vec4* glm_row1 = &ubo.bones[i][0];
        ozz::math::SimdFloat4 ozz_row1 = models_[i].cols[0];
        FbxDouble4 fbx_row1 = InvBind.mData[0];
        glm_row1->x = ozz_row1.m128_f32[0] * fbx_row1.mData[0];
        glm_row1->y = ozz_row1.m128_f32[1] * fbx_row1.mData[1];
        glm_row1->z = ozz_row1.m128_f32[2] * fbx_row1.mData[2];
        glm_row1->w = ozz_row1.m128_f32[3] * fbx_row1.mData[3];

        glm::vec4* glm_row2 = &ubo.bones[i][1];
        ozz::math::SimdFloat4 ozz_row2 = models_[i].cols[1];
        FbxDouble4 fbx_row2 = InvBind.mData[1];
        glm_row2->x = ozz_row2.m128_f32[0] * fbx_row2.mData[0];
        glm_row2->y = ozz_row2.m128_f32[1] * fbx_row2.mData[1];
        glm_row2->z = ozz_row2.m128_f32[2] * fbx_row2.mData[2];
        glm_row2->w = ozz_row2.m128_f32[3] * fbx_row2.mData[3];

        glm::vec4* glm_row3 = &ubo.bones[i][2];
        ozz::math::SimdFloat4 ozz_row3 = models_[i].cols[2];
        FbxDouble4 fbx_row3 = InvBind.mData[2];
        glm_row3->x = ozz_row3.m128_f32[0] * fbx_row3.mData[0];
        glm_row3->y = ozz_row3.m128_f32[1] * fbx_row3.mData[1];
        glm_row3->z = ozz_row3.m128_f32[2] * fbx_row3.mData[2];
        glm_row3->w = ozz_row3.m128_f32[3] * fbx_row3.mData[3];

        glm::vec4* glm_row4 = &ubo.bones[i][3];
        ozz::math::SimdFloat4 ozz_row4 = models_[i].cols[3];
        FbxDouble4 fbx_row4 = InvBind.mData[3];
        glm_row4->x = ozz_row4.m128_f32[0] * fbx_row4.mData[0];
        glm_row4->y = ozz_row4.m128_f32[1] * fbx_row4.mData[1];
        glm_row4->z = ozz_row4.m128_f32[2] * fbx_row4.mData[2];
        glm_row4->w = ozz_row4.m128_f32[3] * fbx_row4.mData[3];
    }
    //  Send updated bone matrices to GPU
    _Mesh->updateUniformBuffer(currentImage,ubo);
}

我正在尝试从mat4构建float4x4,然后将其乘以fbxdouble4float4x4保持动画后的骨骼矩阵,fbxdouble4保持骨骼的反向绑定姿势。 mat4通过UniformBufferObject发送到GPU。

我不确定是否要正确转换float4x4fbxdouble4以便在mat4中使用。我也相信我需要在某个地方glm::transpose,但不能完全确定如何或在何处。现在,我基本上在GPU上变得越来越垃圾:

将`ozz :: math :: float4x4`和`fbxsdk :: fbxdouble4`转换为`glm :: mat4`以进行GPU蒙皮

为了确保我做得透彻,以下是我如何构建骨骼信息(包括绑定姿势)的方法:

FBXObject* Import(const char* File) {
    FbxImporter* Importer = FbxImporter::Create(_FbxManager,"");
    if (!Importer->Initialize(File,-1,_FbxManager->GetIOSettings())) {
        printf("FBX Import Initialize Failed: %s",Importer->GetStatus().GetErrorString());
        return nullptr;
    }

    FbxScene* Scene = FbxScene::Create(_FbxManager,"NewScene");
    Importer->Import(Scene);
    Importer->Destroy();
    GeometryConverter->Triangulate(Scene,true);

    FbxNode* RootNode = Scene->GetRootNode();
    if (RootNode) {
        std::vector<fbxsdk::FbxNode*> Nodes;
        SearchNodes(RootNode,Nodes);
        printf("Nodes Size: %i (%i)\n",RootNode->getchildCount(true),Nodes.size());

        std::vector<Vertex> OutVertices = {};
        std::vector<uint32_t> OutIndices = {};
        std::unordered_map<int,VertexBoneInfo> BoneData = {};

        FBXObject* NewFBX = new FBXObject;

        uint32_t IndexCount = 0;
        for (auto Node : Nodes) {
            FbxMesh* Mesh = (FbxMesh*)Node->GetNodeAttribute();
            FbxVector4* Vertices = Mesh->getcontrolPoints();
            int Deformers = Mesh->GetDeformerCount();
            printf("Deformers %i\n",Deformers);
            FbxSkin* pSkin = (FbxSkin*)Mesh->GetDeformer(0,FbxDeformer::eSkin);
            if (pSkin) {
                int ncBones = pSkin->getclusterCount();
                printf("Bones: %i\n",ncBones);
                for (int boneIndex = 0; boneIndex < ncBones; ++boneIndex)
                {
                    FbxCluster* cluster = pSkin->getcluster(boneIndex);
                    FbxNode* pBone = cluster->GetLink();

                    FbxAMatrix bindPoseMatrix,transformMatrix;
                    cluster->GetTransformMatrix(transformMatrix);
                    cluster->GetTransformLinkMatrix(bindPoseMatrix);
                    NewFBX->bindPoses.push_back(bindPoseMatrix);

                    int* pVertexIndices = cluster->getcontrolPointIndices();
                    double* pVertexWeights = cluster->getcontrolPointWeights();

                    // Iterate through all the vertices,which are affected by the bone
                    int ncVertexIndices = cluster->getcontrolPointIndicesCount();

                    for (int iBoneVertexIndex = 0; iBoneVertexIndex < ncVertexIndices; iBoneVertexIndex++)
                    {
                        // vertex
                        int niVertex = pVertexIndices[iBoneVertexIndex];
                        // weight
                        float fWeight = (float)pVertexWeights[iBoneVertexIndex];

                        BoneData[niVertex].Bones.push_back(boneIndex);
                        BoneData[niVertex].Weights.push_back(fWeight);
                    }
                }
            }
            else {
                printf("Model Has No Skin\n");
            }
            //
            //  UV Mapping
            FbxStringList lUVSetNameList;
            Mesh->GetUVSetNames(lUVSetNameList);
            int UVSets = lUVSetNameList.getcount();
            printf("UV Sets: %i\n",UVSets);
            //if (UVSets > 0) {
                const char* lUVSetName = lUVSetNameList.GetStringAt(0);
                const FbxGeometryElementUV* lUVElement = Mesh->GetElementUV(lUVSetName);
                printf("UV Set Name: %s\n",lUVSetName);
                //if (lUVElement->GetMappingMode() == FbxGeometryElement::eByPolygonVertex) {
                    printf("Polygon Vertex Mapping\n");
                    const bool lUseIndex = lUVElement->GetReferenceMode() != FbxGeometryElement::eDirect;
                    const int lIndexCount = (lUseIndex) ? lUVElement->GetIndexArray().getcount() : 0;
                //}
            //}

            //
            //  Normal Mapping
            FbxGeometryElementNormal* lNormalElement = Mesh->GetElementNormal();

            int lPolyIndexCounter = 0;
            for (int j = 0; j < Mesh->GetPolygonCount(); j++) {
                int NumVerts = Mesh->GetPolygonSize(j);
                if (NumVerts != 3 ) { continue; }
                for (int k = 0; k < NumVerts; k++) {
                    Vertex NewVertex{};
                    //
                    //  Bone Data
                    if (BoneData.count(j) == 1) {
                        const unsigned int Bonesize = BoneData[j].Bones.size();
                        if (Bonesize > 0) {
                            NewVertex.Bones.x = BoneData[j].Bones[0];
                        }
                        if (Bonesize > 1) {
                            NewVertex.Bones.y = BoneData[j].Bones[1];
                        }
                        if (Bonesize > 2) {
                            NewVertex.Bones.z = BoneData[j].Bones[2];
                        }
                        if (Bonesize > 3) {
                            NewVertex.Bones.w = BoneData[j].Bones[3];
                        }

                        const unsigned int WeightSize = BoneData[j].Weights.size();
                        if (WeightSize > 0) {
                            NewVertex.Weights.x = BoneData[j].Weights[0];
                        }
                        if (WeightSize > 1) {
                            NewVertex.Weights.y = BoneData[j].Weights[1];
                        }
                        if (WeightSize > 2) {
                            NewVertex.Weights.z = BoneData[j].Weights[2];
                        }
                        if (WeightSize > 3) {
                            NewVertex.Weights.w = BoneData[j].Weights[3];
                        }
                    }
                    //
                    //  Normap Mapping Data
                    int lNormalIndex = 0;
                    //reference mode is direct,the normal index is same as lIndexByPolygonVertex.
                    if (lNormalElement->GetReferenceMode() == FbxGeometryElement::eDirect)
                        lNormalIndex = lPolyIndexCounter;

                    //reference mode is index-to-direct,get normals by the index-to-direct
                    if (lNormalElement->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
                        lNormalIndex = lNormalElement->GetIndexArray().Getat(lPolyIndexCounter);

                    //Got normals of each polygon-vertex.
                    FbxVector4 lNormal = lNormalElement->GetDirectArray().Getat(lNormalIndex);

                    NewVertex.normal.x = lNormal[0];
                    NewVertex.normal.y = lNormal[1];
                    NewVertex.normal.z = lNormal[2];
                    //
                    //  UV Mapping Data
                    if (lPolyIndexCounter < lIndexCount)
                    {
                        FbxVector2 lUVValue;

                        //the UV index depends on the reference mode
                        int lUVIndex = lUseIndex ? lUVElement->GetIndexArray().Getat(lPolyIndexCounter) : lPolyIndexCounter;

                        lUVValue = lUVElement->GetDirectArray().Getat(lUVIndex);

                        NewVertex.texCoord.x = lUVValue.mData[0];
                        NewVertex.texCoord.y = -lUVValue.mData[1];

                        lPolyIndexCounter++;
                    }
                    //
                    //  Vertex & Index data
                    int VertID = Mesh->GetPolygonVertex(j,k);
                    NewVertex.pos.x = (float)Vertices[VertID].mData[0];
                    NewVertex.pos.y = (float)Vertices[VertID].mData[1];
                    NewVertex.pos.z = (float)Vertices[VertID].mData[2];
                    OutVertices.push_back(NewVertex);
                    OutIndices.push_back(IndexCount++);
                }
            }
        }
        NewFBX->Vertices.swap(OutVertices);
        NewFBX->Indices.swap(OutIndices);
        printf("Out Vertex Count: %i\n",NewFBX->Vertices.size());
        return NewFBX;
    }
}

还有蒙皮着色器:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
    mat4 bones[128];
} ubo;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec4 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in vec3 inNormal;
layout(location = 4) in ivec4 inBones;
layout(location = 5) in vec4 inWeights;

layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec2 fragTexCoord;
layout(location = 2) out vec3 fragNormal;

out gl_PerVertex
{
    vec4 gl_Position;
};

void main() {
    mat4 boneTransform = ubo.bones[inBones[0]] * inWeights[0];
    boneTransform     += ubo.bones[inBones[1]] * inWeights[1];
    boneTransform     += ubo.bones[inBones[2]] * inWeights[2];
    boneTransform     += ubo.bones[inBones[3]] * inWeights[3];

    gl_Position = ubo.proj * ubo.view * ubo.model * boneTransform * vec4(inPosition,1.0);
    fragColor = inColor;
    fragTexCoord = inTexCoord;
}
skyson99599 回答:将`ozz :: math :: float4x4`和`fbxsdk :: fbxdouble4`转换为`glm :: mat4`以进行GPU蒙皮

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3036230.html

大家都在问