Home Game Development Skeletal Mesh with Assimp and OpenGL

Skeletal Mesh with Assimp and OpenGL

0
Skeletal Mesh with Assimp and OpenGL

[ad_1]

I’m making an attempt to animate a skeletal mesh utilizing opengl and assimp and I’m having bother understanding what transforms I would like to use for it to work. From what I perceive, every vertices have bone indices and bone weights which might be static buffers. Theses vertex attribute factors to a bone array uniform that adjustments on each body, relying on the animation time. However, I’m undecided tips on how to receive the bone array uniform.

More exactly, I would really like extra info on aiBone::mOffsetMatrix and aiNodeAnim on tips on how to mix them to acquire the bone remodel uniform to ship to the GPU.

Right now, I’ve code that appears like this:

// Loading bone information
for (uint32 index_bone = 0; index_bone < ai_mesh.mNumBones; ++index_bone)
{
    const aiBone& ai_bone = *ai_mesh.mBones[index_bone];

    bone bone = {
        .title = ai_bone.mName.C_Str(),
        .bone_id = ai_bone_id,
        .remodel = to_mat4(ai_bone.mOffsetMatrix),
    };
    
    bones.emplace_back(std::transfer(bone));

    for (uint32 index_weight = 0; index_weight < ai_bone.mNumWeights; ++index_weight)
    {
        const aiVertexWeight& ai_bone_weight = ai_bone.mWeights[index_weight];
        vertex& vertex = vertices.at(ai_bone_weight.mVertexId);
        vertex.add_bone_weight(index_bone, ai_bone_weight.mWeight);
    }
}
// Loading animation
animation to_animation(const asset_metadata& metadata, const aiScene& ai_scene, const aiAnimation& ai_animation) const
{
    animation animation;

    animation.title = ai_animation.mName.C_Str();
    animation.length = static_cast<float32>(ai_animation.mDuration);
    animation.fps = static_cast<float32>(ai_animation.mTicksPerSecond);

    const auto add_frames = [&](uint32 bone_id, uint32 ai_frame_num, const auto* ai_frames, auto&& func) {
        for (uint32 index = 0; index < ai_frame_num; ++index)
        {
            const auto& ai_frame = ai_frames[index];

            animation_frame body {
                .key = animation_frame_key {
                    .bone_id = bone_id,
                    .time = static_cast<float32>(ai_frame.mTime),
                },
            };

            func(ai_frame, body);

            animation.add_frame(std::transfer(body));
        }
    };

    const auto add_frame_translation = [&](const auto& ai_frame, animation_frame& body) {
        body.remodel.translation = to_vec3(ai_frame.mValue);
    };

    const auto add_frame_rotation = [&](const auto& ai_frame, animation_frame& body) {
        body.remodel.rotation = to_quat(ai_frame.mValue);
    };

    const auto add_frame_scaling = [&](const auto& ai_frame, animation_frame& body) {
        body.remodel.scale = to_vec3(ai_frame.mValue);
    };

    for (uint32 index = 0; index < ai_animation.mNumChannels; ++index)
    {
        const aiNodeAnim* ai_node_anim = ai_animation.mChannels[index];

        add_frames(index, ai_node_anim->mNumPositionKeys, ai_node_anim->mPositionKeys, add_frame_translation);
        add_frames(index, ai_node_anim->mNumRotationKeys, ai_node_anim->mRotationKeys, add_frame_rotation);
        add_frames(index, ai_node_anim->mNumScalingKeys, ai_node_anim->mScalingKeys, add_frame_scaling);

        const auto predicate = [&](const aiNode& ai_node) {
            return ai_node.mName == ai_node_anim->mNodeName;
        };

        const aiNode* ai_node = find_node(ai_scene.mRootNode, predicate);

        if (ai_node == nullptr)
        {
            SPDLOG_WARN("animation node not discovered, scene={} animation={} node={}", metadata.title, animation.title.get(), ai_node_anim->mNodeName.C_Str());
            proceed;
        }

        const auto to_scene_transform = [&](animation_frame& body) {
            for (const aiNode* ai_node_parent = ai_node; ai_node_parent != nullptr; ai_node_parent = ai_node_parent->mParent)
            {
                body.remodel += to_transform(ai_node_parent->mTransformation);
            }
        };

        animation.for_each_frames_of(index, to_scene_transform);
    }

    return animation;
}
// Binding uniform
const auto update_bones = [&](const animation_frame& body) {
    mesh_instance.bone_transforms[frame.key.bone_id] = body.remodel.to_mat();
};

float32 animation_time = std::fmod(time, animation.length);

animation.for_each_frames_in(animation_time, animation_time + 16.6666f, update_bones);

if (uniform_bones != spore::opengl::invalid_id)
{
    glProgramUniformMatrix4fv(shader_program.program_id, uniform_bones, mesh_instance.bone_transforms.dimension(), GL_FALSE, &mesh_instance.bone_transforms[0][0][0]);
}

This shouldn’t be everything of the code, however it’s the gist of it. Thank for the assistance!

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here