Commit e544a420 authored by Lázár Bence Kis's avatar Lázár Bence Kis
Browse files

Primitive animation blending

parent 0ce6bebb
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -184,6 +184,10 @@ namespace anim {
        return low + t * (high - low);
    }

    static vec3 linear_interpolate(vec3 low, vec3 high, double t) {
        return low + vec3(t, t, t) * (high - low);
    }

    static double linear_interpolate(double t_low, double low, double t_high, double high, double t) {
        double dt = (t - t_low) / (t_high - t_low);
        return linear_interpolate(low, high, dt);
@@ -595,11 +599,15 @@ namespace anim {
            for (auto i : items()) {
                if (auto anim = dynamic_cast<anim::AnimationTrack*>(i)) {
                    auto val = anim->update(m_current_time);
                    anim->target()->reflection()->functions().at(anim->m_property_setter_name).code({ val });
                    process_value(anim, val);
                }
            }
        }

        virtual void process_value(anim::AnimationTrack *anim, com::Reflection::ValuePtr val) {
            anim->target()->reflection()->functions().at(anim->m_property_setter_name).code({ val });
        }

        template<class... ParameterTypes>
        AnimationTrack* add_track(ParameterTypes... args) {
            auto track = push_back<anim::AnimationTrack>(args...);
@@ -616,4 +624,15 @@ namespace anim {
        bool reversed = false;
    };

    struct BlendableAnimation : public Animation
    {
        using Animation::Animation;

        void process_value(anim::AnimationTrack *anim, com::Reflection::ValuePtr val) override {
            m_values[&(anim->target()->reflection()->functions().at(anim->m_property_setter_name))] = val;
        }

        std::unordered_map<const com::Reflection::Function*, com::Reflection::ValuePtr> m_values;
    };
    
}
+3 −0
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@ struct Animator : public com::Runner
{
    static inline std::string self_name() { return "animator.run"; }

    static float blending_factor_alpha;
    static bool select_animation_a;

    COM_REFLECTION_USINGS();

    Animator() : Animator(self_name(), {}) {}
+56 −0
Original line number Diff line number Diff line
@@ -6,6 +6,9 @@

namespace anim {

float Animator::blending_factor_alpha = 0.f;
bool Animator::select_animation_a = true;

Animator::Animator(std::string const& name, std::vector<std::uint8_t> const& json)
    : com::Runner{ name }
    , m_json{ json.begin(), json.end() }
@@ -55,6 +58,59 @@ void Animator::next_round()
        }
    }

    if (select_animation_a) {
        blending_factor_alpha = max(0.f, blending_factor_alpha - 0.02);
    }
    else {
        blending_factor_alpha = min(1.f, blending_factor_alpha + 0.02);
    }

    std::unordered_map<const com::Reflection::Function*, std::vector<com::Reflection::ValuePtr>> values;
    auto blend_folder = com::Folder::root()->find<com::Folder>(ANIM_FOLDER_NAME)->find<com::Folder>("blended");
    for (auto anim_container : blend_folder->subfolders()) {
        if (auto animation = dynamic_cast<anim::BlendableAnimation*>(anim_container)) {
            animation->update(t);
            for (auto& [parameter, value]: animation->m_values) {
                if (!values.contains(parameter)) {
                    values[parameter] = std::vector<com::Reflection::ValuePtr>{};
                }
                values[parameter].push_back(value);
            }
        }
    }
    for (auto& [parameter, values_to_blend]: values) {
        if (values_to_blend.size() == 1) {
            parameter->code({ values_to_blend[0] });
        }
        else {
            switch (parameter->param_types[0]) {
            case com::Reflection::TypeID::FLOAT: {
                float a = com::as<com::Reflection::ValueFLOAT>(values_to_blend[0])->value;
                float b = com::as<com::Reflection::ValueFLOAT>(values_to_blend[1])->value;
                float result = linear_interpolate(a, b, blending_factor_alpha);
                parameter->code({ com::make_value<ValueFLOAT>(result) });
                break;
            }
            case com::Reflection::TypeID::VEC3: {
                vec3 a = com::as<com::Reflection::ValueVEC3>(values_to_blend[0])->value;
                vec3 b = com::as<com::Reflection::ValueVEC3>(values_to_blend[1])->value;
                vec3 result = linear_interpolate(a, b, blending_factor_alpha);
                parameter->code({ com::make_value<ValueVEC3>(result) });
                break;
            }
            case com::Reflection::TypeID::QUAT: {
                quat a = com::as<com::Reflection::ValueQUAT>(values_to_blend[0])->value;
                quat b = com::as<com::Reflection::ValueQUAT>(values_to_blend[1])->value;
                quat result = slerp(a, b, blending_factor_alpha);
                parameter->code({ com::make_value<ValueQUAT>(result) });
                break;
            }
            default:
                ASSUMPTION(false);
            }
        }
    }
    
    // auto v = com::make_default_value<com::Reflection::ValueVEC3>();
    // box.reflection()->functions().at("set_origin").code(v);
    
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ void boot(com::Folder* const ctx_root)
    com::Folder* const root_scr = ctx_root->push_back<com::Folder>(ANIM_FOLDER_NAME);
    root_scr->push_back<Animator>();
    root_scr->push_back<com::Folder>("animations");
    root_scr->push_back<com::Folder>("blended");
    root_scr->push_back<com::Folder>("skeletons");
    // root_scr->push_back<Console>(); 
}
+7 −1
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <implot.h>
#include <implot_internal.h>
#include <anim/animation.hpp>
#include <anim/animator.hpp>
#include <SDL2/SDL_video.h>
#include <osi/index.hpp>
#include <gfx/index.hpp>
@@ -218,6 +219,7 @@ void render() {
    static int prevSegment = 0;
    static int interpolationIdx = static_cast<int>(edited_track->m_keyframes[segment]->interpolation);
    static float smoothness = -2.f;
    static float blend = 0.f;
    
    std::vector<std::string> animation_labels;
    for (auto a : animfold->subfolders()) {
@@ -246,7 +248,8 @@ void render() {
    
    ImGui::Checkbox("Loop", &edited_animation->loop); ImGui::SameLine();
    ImGui::Checkbox("Paused", &edited_animation->paused); ImGui::SameLine();
    ImGui::Checkbox("Reversed", &edited_animation->reversed);
    ImGui::Checkbox("Reversed", &edited_animation->reversed); ImGui::SameLine();
    ImGui::Checkbox("Blend A", &anim::Animator::select_animation_a);
    
    ImGui::PushItemWidth(100);
    // ImGui::Combo("##animation", &edited_animation_index, animation_labels, IM_ARRAYSIZE(animation_labels)); ImGui::SameLine();
@@ -284,6 +287,9 @@ void render() {
    ImGui::PushItemWidth(100);
    ImGuiSliderFlags slider_flags = ImGuiSliderFlags_Logarithmic;
    ImGui::DragFloat("smoothness", &smoothness, 0.02f, -10.f, 10.f, nullptr, slider_flags);
    ImGui::SameLine();
    
    ImGui::DragFloat("blend", &anim::Animator::blending_factor_alpha, 0.002f, 0.f, 1.f, nullptr);
    ImGui::PopItemWidth();