微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

assimp:以正确的方式加载“mTransformation”和“mOffsetMatrix”如何从 assimp 加载骨骼动画?

如何解决assimp:以正确的方式加载“mTransformation”和“mOffsetMatrix”如何从 assimp 加载骨骼动画?

我目前正在尝试从 collada 文件 (.dae) 加载骨架动画。 但是我的代码中似乎有一个我自己找不到的错误

错误可视化为根本不显示层次结构的最后一个孩子。 它们已加载,但以消失的方式进行了转换。

我尝试根据需要提供尽可能密集的代码 spinets,以了解我在做什么。 如果您需要更多上下文,请提出要求!

我用于加载骨骼变换的代码

其中 bone_map 是从 assimp 关节名称转换为我的关节数组的映射。

mesh.joint_local_transformations = std::make_unique<glm::mat4[]>(ai_mesh->mNumBones);
mesh.joint_global_inverse_transformations = std::make_unique<glm::mat4[]>(ai_mesh->mNumBones);
mesh.joint_count = ai_mesh->mNumBones;

for (uint32_t i = 0; i < ai_mesh->mNumBones; ++i)
{
  const auto *joint = ai_mesh->mBones[i];
  if (bone_map.contains(joint->mName.data))
  {
    const auto joint_index = bone_map.at(joint->mName.data);

    auto joint_transformation_invert = fromaimat4(joint->mOffsetMatrix);

    const auto *node = find_node(joint->mName,ai_scene);
    auto joint_transformation = fromaimat4(node->mTransformation);

    mesh.joint_global_inverse_transformations[joint_index] = joint_transformation_invert;
    mesh.joint_local_transformations[joint_index] = joint_transformation;
  }
}

我用于加载动画转换的代码

anim.joint_transformations = std::make_unique<Animation::JointTransformation[]>(anim.key_frame_count * anim.joint_count);

for (size_t i = 0; i < anim.key_frame_count; ++i)
{
  for (size_t j = 0; j < ai_anim->mNumChannels; ++j)
  {
    if (bone_map.contains(ai_anim->mChannels[j]->mNodeName.data))
    {
      const auto bone_index = bone_map.at(ai_anim->mChannels[j]->mNodeName.data);

      const auto r = ai_anim->mChannels[j]->mRotationKeys[i].mValue;
      const auto s = ai_anim->mChannels[j]->mScalingKeys[i].mValue;
      const auto p = ai_anim->mChannels[j]->mPositionKeys[i].mValue;

      Animation::JointTransformation t{};
      t.rotation = {r.w,r.x,r.y,r.z};
      t.scale = {s.x,s.y,s.z};
      t.translation = {p.x,p.y,p.z};
      anim.joint_transformations[anim.joint_count * i + bone_index] = t;
    }
  }
}

我用来制作动画的代码

其中 i 是当前关键帧索引,j 是当前联合索引。

其中 joints 是传递到着色器的转换数组。 (结果)

请注意,父项的索引始终低于子项。因此,始终首先处理父级。

const auto *f0 = &(anim->joint_transformations[(i - 1) * anim->joint_count]);
const auto *f1 = &(anim->joint_transformations[(i - 0) * anim->joint_count]);

joints[0] = Animation::mix(f0[0],f1[0],current_time);

for (uint32_t j = 1; j < mesh->joint_count; ++j)
{
    const auto &parent = joints[mesh->joint_parent_indices[j]];
    joints[j] = parent * Animation::mix(f0[j],f1[j],current_time);
}

for (uint32_t j = 0; j < mesh->joint_count; ++j)
{
    joints[j] = joints[j] * mesh->joint_global_inverse_transformations[j];
}

使用的数据结构(可能与问题无关):

struct Mesh
{
    std::unique_ptr<glm::vec3[]> vertices;
    std::unique_ptr<uint32_t[]> indices;
    std::unique_ptr<glm::vec3[]> normals;
    std::unique_ptr<glm::vec2[]> tex_coords;

    uint32_t vertex_count;
    uint32_t indices_count;
};

struct AnimatedMesh
        : public Mesh
{
    std::unique_ptr<uint32_t[]> joint_indices;
    std::unique_ptr<float[]> joint_weights;

    std::unique_ptr<glm::mat4[]> joint_local_transformations;
    std::unique_ptr<glm::mat4[]> joint_global_inverse_transformations;
    std::unique_ptr<uint32_t[]> joint_parent_indices;

    uint32_t joint_count;
    uint32_t joints_per_vertex = 3;
};

struct Animation
{
    struct JointTransformation
    {
        glm::vec3 translation;
        glm::quat rotation;
        glm::vec3 scale;
    };

    std::unique_ptr<JointTransformation[]> joint_transformations;
    std::unique_ptr<float[]> joint_timestamps;

    uint32_t joint_count;
    uint32_t key_frame_count;

    static glm::mat4 mix (const JointTransformation &t0,const JointTransformation &t1,float delta)
    {
        const auto t = glm::translate(glm::identity<glm::mat4>(),glm::mix(t0.translation,t1.translation,delta));
        const auto r = glm::toMat4(glm::slerp(t0.rotation,t1.rotation,delta));
        const auto s = glm::scale(glm::identity<glm::mat4>(),glm::mix(t0.scale,t1.scale,delta));
        return t * r * s;
    }
};

感谢所有试图提供帮助的人!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。