zoukankan      html  css  js  c++  java
  • GDC动手做-战争机器的高性能动画过渡技术(1)

    视频地址

    Inertialization: High-Performance Animation Transitions in Gears of War
    https://www.youtube.com/watch?v=BYyv4KTegJI&list=PL2e4mYbwSTbbHAJT7OdK5mv-idhlLOTl0&index=10

    0x0 惯性插值和线性插值

    该技术称为inertialization,微软为这个技术自己发明的新词汇,这里翻译成惯性插值。本质是多项式曲线插值。我们常用的线性插值是关于t的一次函数,而inertialization是5次。回顾一下线性插值,起始值x0和目标值x1,xt关于t的表达式为xt=(1-t)x0+tx1。当t=0时,xt=x0,当t=1时,xt=x1。惯性插值这项技术将速度和加速度,加速度的变化率(jerk)也纳入插值的考量中,维持起始值x0的速度v0和加速度a0不变,当t趋向1时,v0和a0趋向于0。因此惯性插值特别适合用在从运动到静止动画的插值。视频中举了2给例子,一个是持握武器更换方向到idle的过渡,另一个是挥手到idle的过渡。

    0x0 优点

    1.性能开销恒定。对比blend,blend开销随着动画数量增长而增长
    2.不需要因过渡的需要而记录额外变量
    3.动作过渡更自然,比如挥手到idle。但不适用于所有情况,比如反过来恐怕就不那么自然了

    0x1 核心算法

    只考虑1维的情况下,视频的这张图包含了全部算法。

    惯性插值需要5个参数
    curentValue 当前值
    prevValue 当前值的上一个值
    targetValue 目标值
    t1 当前值和上一个值之间的时间间隔

    初始速度v0和初始加速度a0可以通过公式带入得到,其中v0<0,a0>0

    下面把公式转换成代码

    
        public class InertializationMath
        {
            /// <summary>
            /// 惯性插值
            /// </summary>
            /// <param name="curentValue">当前值</param>
            /// <param name="prevValue">上一个值</param>
            /// <param name="targetValue">目标值</param>
            /// <param name="t1">当前值和上一个值的时间间隔</param>
            /// <param name="t"></param>
            /// <returns></returns>
            public static float Lerp(float curentValue,float prevValue,float targetValue, float t1, float t)
            {
                float x0 = curentValue - targetValue;
                float v0 = (curentValue - prevValue)/t1;
                return Lerp(x0, v0, t1, t);
            }
    
    public static float Lerp(float x0, float v0, float t1, float t)
            {
                float tf2 = t1 * t1;
                float tf3 = tf2 * t1;
                float tf4 = tf3 * t1;
                float tf5 = tf4 * t1;
    
                float a0 = (-8 * v0 * t1 - 20 * x0) / (t1 * t1);
                a0 = Mathf.Max(0, a0);
    
                float A = -(a0 * tf2 + 6 * v0 * t1 + 12 * x0) / (2 * tf5);
                float B = (3 * a0 * tf2 + 16 * v0 * t1 + 30 * x0) / (2 * tf4);
                float C = -(3 * a0 * tf2 + 12 * v0 * t1 + 20 * x0) / (2 * tf3);
    
                float t2 = t * t;
                float t3 = t2 * t;
                float t4 = t3 * t;
                float t5 = t4 * t;
    
                float xt = A * t5 + B * t4 + C * t3 + (a0 / 2) * t2 + v0 * t + x0;
    
                return xt;
            }
        }
    
    

    建立一个demo场景,填入你想要的参数,然后对t进行采样,使用linerenderer画下曲线,效果如下

    我们成功描画出了1维惯性缓动曲线。下一篇将缓动应用到3d的位移和旋转中,敬请期待。

  • 相关阅读:
    MAC下通过改apache配置文件切换php多版本的方法
    mac配置php7运行环境
    VS Code 配置 C/C++ 环境(转)
    go语言中goroute使用:=遇到的坑
    python中执行shell的两种方法总结
    对于pycharm和vscode下,从外部复制文本内容为python字符串内容是会自动加u202a解决办法
    在macOS下正确配置 VS Code 使用 virtualenv 里的 python 环境参数
    github上传时出现error: src refspec master does not match any解决办法
    VSCode tasks.json中的各种替换变量的意思 ${workspaceFolder} ${file} ${fileBasename} ${fileDirname}等
    Sonar入门(四):Eclipse集成Sonar
  • 原文地址:https://www.cnblogs.com/terrynoya/p/14711883.html
Copyright © 2011-2022 走看看