我目前正在尝试从 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;
}
}
}
我用来制作动画的代码:
wherei
是当前关键帧索引,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;
}
};
感谢所有试图提供帮助的人!