[自研引擎]GAMES104 动画系统

目录

引言

一、实现走跑跳状态机

二、走跑跳过渡动画

三、结果展示

引言

本次作业为作业3的内容,我们需要在Piccolo项目上拉取分支games104/homework03-animation-physics,可以通过git进行拉取,输入命令 git clone -b games104/homework03-animation-physics + 项目地址  如下:

一、实现走跑跳状态机

在Piccolo小引擎代码中找到Piccolo/engine/source/runtime/function/animation/animation_FSM.cpp,找到update函数补充代码,实现机器人走跑跳状态机

根据状态机示意图,补全代码即可,下来我会简单梳理一下状态机逻辑

switch结构首先会根据上一帧结束时的状态决定下一帧开始时的状态

状态机最开始的时候指向_idle,接下来有两个数字1和2表示动作的优先级,当is_jumping为真时,会进入jump_start_from_idle状态,当is_moving为真时,会进入到walk_start状态,剩余状态同理,根据当前状态以及bool变量的值来决定!

补全代码如下:

bool AnimationFSM::update(const json11::Json::object& signals)
    {
        States last_state     = m_state;
        bool   is_clip_finish = tryGetBool(signals, "clip_finish", false);
        bool   is_jumping     = tryGetBool(signals, "jumping", false);
        float  speed          = tryGetFloat(signals, "speed", 0);
        bool   is_moving      = speed > 0.01f;
        bool   start_walk_end = false;

        //switch结构根据上一帧结束时的状态选择  决定下一帧开始时的状态
        switch (m_state)
        {
            case States::_idle:
                /**** [0] ****/
                if(is_jumping){
                    m_state = States::_jump_start_from_idle;
                    break;
                }
                if(is_moving){
                    m_state = States::_walk_start;
                    break;
                }
                break;

            case States::_walk_start:
                /**** [1] ****/
                if(is_clip_finish){
                    m_state = States::_walk_run;
                    break;
                }
                break;

            case States::_walk_run:
                /**** [2] ****/
                if(is_jumping){
                    m_state = States::_jump_start_from_walk_run;
                    break;
                }
                if(start_walk_end && is_clip_finish){
                    m_state = States::_walk_stop;
                    break;
                }
                if(!is_moving){
                    m_state = States::_idle;
                }
                break;

            case States::_walk_stop:
                /**** [3] ****/
                if(!is_moving && is_clip_finish){
                    m_state = States::_idle;
                }
                break;

            case States::_jump_start_from_idle:
                /**** [4] ****/
                if(is_clip_finish){
                    m_state = States::_jump_loop_from_idle;
                }
                break;

            case States::_jump_loop_from_idle:
                /**** [5] ****/
                if(!is_jumping){
                    m_state = States::_jump_end_from_idle;
                }
                break;

            case States::_jump_end_from_idle:
                /**** [6] ****/
                if(is_clip_finish){
                    m_state = States::_idle;
                }
                break;

            case States::_jump_start_from_walk_run:
                /**** [7] ****/
                if(is_clip_finish){
                    m_state = States::_jump_loop_from_walk_run;
                }
                break;

            case States::_jump_loop_from_walk_run:
                /**** [8] ****/
                if(!is_jumping){
                    m_state = States::_jump_end_from_walk_run;
                }
                break;

            case States::_jump_end_from_walk_run:
                /**** [9] ****/
                if(is_clip_finish){
                    m_state = States::_walk_run;
                }
                break;

            default:
                break;
        }
        //判断 last_state 是否等于 m_state
        //表示状态发生了改变 还是 状态未改变
        return last_state != m_state;
    }

二、走跑跳过渡动画

只有状态的转换可不行,走跑跳之间骨骼的过渡也是动画的一部分,这样才能看起来很自然!

所以还需要补全blend函数,在Piccolo小引擎中找到Piccolo/engine/source/runtime/function/animation/pose.cpp,对走跑跳进行一个过渡,代码都有详细的注释

//混合函数  接受一个AnimationPose类型的参数 pose
void AnimationPose::blend(const AnimationPose& pose)
{
    //遍历数组m_bone_poses中所有数组
    for (int i = 0; i < m_bone_poses.size(); i++)
    {
        //表示当前动画姿势的骨骼变换
        auto&       bone_trans_one = m_bone_poses[i];
        //表示传入的动画姿势pose的骨骼变换
        const auto& bone_trans_two = pose.m_bone_poses[i];

        //计算两个关键帧的权重之和,用于后续的归一化操作
        float sum_weight = m_weight.m_blend_weight[i] + pose.m_weight.m_blend_weight[i];
        if (sum_weight != 0)
        {
            //计算当前姿势的权重   要混合的姿势pose的权重与总权重之比
            float cur_weight = m_weight.m_blend_weight[i] / sum_weight;
            //将要混合姿势pose的权重赋值给当前姿势的权重,用于后续的权重比较
            m_weight.m_blend_weight[i] = pose.m_weight.m_blend_weight[i];
            //使用线性插值函数lerp对当前姿势的位置进行混合
            bone_trans_one.m_position  = Vector3::lerp(bone_trans_one.m_position, bone_trans_two.m_position,1 - cur_weight);
            //使用线性插值函数lerp对当前姿势的缩放进行混合
            bone_trans_one.m_scale     = Vector3::lerp(bone_trans_one.m_scale, bone_trans_two.m_scale, 1 - cur_weight);
            //使用球面线性插值函数sLerp对当前姿势的旋转进行混合
            bone_trans_one.m_rotation  = Quaternion::sLerp(1 - cur_weight, bone_trans_one.m_rotation, bone_trans_two.m_rotation, true);
        }
    }
}

三、结果展示

走跑跳

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值