Скелетная анимация с OpenGL 4 и FBX SDK; В чем моя проблема?

Прежде всего, посмотрите мой потрясающий результат:

Эта модель без шкуры:

Проблема в том, что что-то не так, но я не могу понять, что это такое. Это код импорта анимации с помощью FBX SDK:

void FbxLoader::processAnimation(FbxNode* fbxNode, std::string_view animationName, f64 frameRate, f64 stopTime)
{
    auto bone = mModel->getSkeleton()->getHierarchy(StringHash(fbxNode->GetName()));
    if (!bone) {
        return;
    }

    auto animationSet = new KeyFrameSet{animationName};
    f64 invFrameRate = 1.0 / frameRate;

    FbxTime animationTime{};
    f64 currTime = 0.0;
    while (currTime <= stopTime) {
        animationTime.SetSecondDouble(currTime);

        auto localTransform = fbxNode->EvaluateLocalTransform(animationTime);
        animationSet->addKeyFrame(ToMat4(localTransform));

        currTime += invFrameRate;
    }

    bone->addAnimationSet(animationSet);
}

Честно говоря, я новичок в FBX SDK, поэтому я очень озадачен тем, что это правильный код для получения позы связывания.

При расчете матриц Sking гарантируется, что root -> parent -> child order, поэтому я подумал, что это может сработать. Это расчет кода скининга матриц:

void Skeleton::update(AnimationController* animationController)
{
    auto currAnimationClip = animationController->getCurrAnimationClip();

    std::vector<glm::mat4> boneTransforms(mHierarchy.size());

    u32 currKeyFrameIndex = animationController->getCurrKeyFrameIndex();
    u32 nextKeyFrameIndex = animationController->getNextKeyFrameIndex();
    f32 delta = animationController->getDelta();

    glm::mat4 invBindPose{};
    glm::mat4 pose{}; // local pose
    glm::mat4 parentPose{}; // local pose of parent

    for (usize i = 0; i < mHierarchy.size(); ++i) {
        auto bone = mHierarchy[i];
        invBindPose = bone->getInvBindPose();

        auto animationSet = bone->getKeyFrameSet(currAnimationClip->getName());
        auto currKeyFrame = animationSet->getKeyFrameAt(currKeyFrameIndex);
        auto nextKeyFrame = animationSet->getKeyFrameAt(nextKeyFrameIndex);

        auto currRotation = currKeyFrame.getRotation();
        auto nextRotation = nextKeyFrame.getRotation();

        auto rotation = glm::slerp(currRotation, nextRotation, delta);
        pose = glm::mat4_cast(rotation);

        auto currTranslation = currKeyFrame.getTranslation();
        auto nextTransaltion = nextKeyFrame.getTranslation();

        auto translaion = glm::mix(currTranslation, nextTransaltion, delta);
        pose[3] = glm::vec4{translaion, 1.0f};
        // if root, identity matrix
        i32 parentIndex = bone->getParentIndex();
        parentPose = parentIndex < 0 ? glm::mat4{1.0f} : boneTransforms[parentIndex];

        boneTransforms[i] = pose * parentPose;
        // I think skin transfrom will be global inverse bind pose, because boneTransforms[i] is global pose matrix...
        mSkinTransforms[i] = invBindPose * boneTransforms[i];
    }
}

Затем я отправляю скининговые матрицы в вершинный шейдер:

#version 450 core

struct Phong {
    vec3 n;
    vec3 l;
    vec3 v;
};

layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
layout(location = 2) in vec3 a_Normal;
layout(location = 10) in uvec4 a_SkinIndex;
layout(location = 11) in vec4 a_SkinWeight;

uniform mat4 u_ModelViewMatrix;
uniform mat4 u_NormalMatrix;
uniform mat4 u_Projection;
uniform mat4 u_SkinMatrices[100];
uniform vec3 u_LightPosition;

out Phong v_Phong;

void main(void) {
    vec4 position = u_ModelViewMatrix * vec4(a_Position, 1.0);

    position
        = (u_SkinMatrices[a_SkinIndex.x] * position) * a_SkinWeight.x
        + (u_SkinMatrices[a_SkinIndex.y] * position) * a_SkinWeight.y
        + (u_SkinMatrices[a_SkinIndex.z] * position) * a_SkinWeight.z
        + (u_SkinMatrices[a_SkinIndex.w] * position) * a_SkinWeight.w;

    v_Phong.n = mat3(u_NormalMatrix) * a_Normal;
    v_Phong.l = u_LightPosition - a_Position.xyz;
    v_Phong.v = -a_Position.xyz;

    gl_Position = u_Projection * position;
}

Я полностью потерян. Ребята, можете ли вы дать мне совет?

0 ответов

Другие вопросы по тегам