多項式でいい感じのeasingを作ろう
$ f(0) = 0 ― x=0のとき0
$ f(1) = 1 ― x=1のとき1
$ f'(0) = 0 ― x=0のとき速度0
$ f'(1) = 0 ― x=1のとき速度0
$ f''(0) = 0 ― x=0のとき加速度0
$ f''(1) = 0 ― x=1のとき加速度0
これらを満たすいい感じのカーブを作りたい ベジエ実装めんどいので
たとえば、5次式の場合($ f''(0) = 0を満たさない2次より下は省略)
$ f(x) = a x^5 + b x^4 + c x^3
$ f'(x) = 5a x^4 + 4b x^3 + 3c x^2
$ f''(x) = 20a x^3 + 12b x^2 + 6c x
これより、以下の3式
$ f(1) = a + b + c = 1
$ f'(1) = 5a + 4b + 3c = 0
$ f''(1) = 20a + 12b + 6c = 0
が導き出される これどうすんの
$ {\rm smootherstep}(x) = 6 x^5 - 15 x^4 + 10 x^3
WolframAlpha先生に聞いてみたら、答えは一つしかなく、このSmootherstepだけらしい
じゃあ6次だ!
$ f(x) = a x^6 + b x^5 + c x^4 + d x^3
$ f'(x) = 6a x^5 + 5b x^4 + 4c x^3 + 3d x^2
$ f''(x) = 30a x^4 + 20b x^3 + 12c x^2 + 6d x
これより、以下の3式
$ f(1) = a + b + c + d = 1
$ f'(1) = 6a + 5b + 4c + 3d = 0
$ f''(1) = 30a + 20b + 12c + 6d = 0
が導き出される
WolframAlpha先生によると、
$ b = 6 - 3a
$ c = 3a - 15
$ d = 10 - a
とのこと よさそう
https://gyazo.com/d8cca9571beb9fab3c68fef241d59100
あれーーー 値域が下に行っちゃった
7次に増やして
$ f'''(0) \geq 0
$ f'''(1) \geq 0
も制約に加えたほうが良さそう
このあたりから$ eを変数に置くと怒られが発生してくる
$ f(x) = a_7 x^7 + a_6 x^6 + a_5 x^5 + a_4 x^4 + a_3 x^3
$ f'(x) = 7a_7 x^6 + 6a_6 x^5 + 5a_5 x^4 + 4a_4 x^3 + 3a_3 x^2
$ f''(x) = 42a_7 x^5 + 30a_6 x^4 + 20a_5 x^3 + 12a_4 x^2 + 6a_3 x
$ f'''(x) = 210a_7 x^4 + 120a_6 x^3 + 60a_5 x^2 + 24a_4 x + 6a_3
制約は以下の5つ:
$ f(1) = a_7 + a_6 + a_5 + a_4 + a_3 = 1
$ f'(1) = 7a_7 + 6a_6 + 5a_5 + 4a_4 + 3a_3 = 0
$ f''(1) = 42a_7 + 30a_6 + 20a_5 + 12a_4 + 6a_3 = 0
$ f'''(0) = 6a_3 > 0
$ f'''(1) = 210a_7 + 120a_6 + 60a_5 + 24a_4 + 6a_3 > 0
とはいえ3つの制約でとりあえずやればよさそうか
WolframAlphaによると
$ a_5 = -6a_7 - 3a_6 + 6
$ a_4 = 8a_7 + 3a_6 - 15
$ a_3 = -3a_7 - a_6 + 10
2変数になっていい感じ
https://gyazo.com/74b35554fddf39a9edcaf407c670afed
いい感じだけど調整むっず
残り2つの制約を吟味してみる
$ 6a_3 > 0
$ \longrightarrow a_3 = -3a_7 - a_6 + 10 > 0
$ \longrightarrow -3a_7 > a_6 - 10
あーね
$ 210a_7 + 120a_6 + 60a_5 + 24a_4 + 6a_3 > 0
$ \longrightarrow 210a_7 + 120a_6 + 60( -6a_7 - 3a_6 + 6 ) + 24( 8a_7 + 3a_6 - 15 ) + 6( -3a_7 - a_6 + 10 ) > 0
$ \longrightarrow 24a_7 + 6a_6 + 60 > 0
$ \longrightarrow 4a_7 > -a_6 - 10
おー
https://gyazo.com/8de9c0ccdf4139bc5a866d02b8d896be
こんなかんじ
了解!
ちょうど$ a_7 = -20が尖っている箇所らしく、この交点$ a_7 = -20, a_6 = 70がSmootheststepらしい!ワオ!
ちなみに$ a_7 = 0、$ a_6 = 0にするとちゃんとSmootherstepです
触りやすいようにパラメタ$ kで$ a_6を制御してみる
$ a_6 = {\rm lerp}(-4a_7 - 10, -3a_7 + 10, k)
https://gyazo.com/b2522a2ec98fbe44bddc6912eb6c4f9c
ちょうど$ kがグラフの形を左右対称に変える媒介変数になっててめちゃくちゃ良い感じ
ウェ~イ
おまけ
でこれライブコーディングで使えんの?
5つも符号付きで数字覚えたいですか
続行: 加速度ゼロ制約なしだとどうなんの
以下の6つの制約で出してみる
$ f(0) = 0 ― x=0のとき0
$ f(1) = 1 ― x=1のとき1
$ f'(0) = 0 ― x=0のとき速度0
$ f'(1) = 0 ― x=1のとき速度0
$ f''(0) \geq 0 ― x=0のとき加速度0以上
$ f''(1) \leq 0 ― x=1のとき加速度0以下
2次項を加えて様子拝見
$ f(x) = a_7 x^7 + a_6 x^6 + a_5 x^5 + a_4 x^4 + a_3 x^3 + a_2 x^2
$ f'(x) = 7a_7 x^6 + 6a_6 x^5 + 5a_5 x^4 + 4a_4 x^3 + 3a_3 x^2 + 2a_2 x
$ f''(x) = 42a_7 x^5 + 30a_6 x^4 + 20a_5 x^3 + 12a_4 x^2 + 6a_3 x + 2a_2
0と1を代入するとこんな感じ
$ f''(0) = 2a_2 \geq 0
$ f(1) = a_7 + a_6 + a_5 + a_4 + a_3 + a_2 = 1
$ f'(1) = 7a_7 + 6a_6 + 5a_5 + 4a_4 + 3a_3 + 2a_2 = 0
$ f''(1) = 42a_7 + 30a_6 + 20a_5 + 12a_4 + 6a_3 + 2a_2 \leq 0
$ f(1)と$ f'(1)の解をとったらこんな感じ
$ a_3 = -5a_7 - 4a_6 - 3a_5 - 2a_4 - 2
$ a_2 = 4a_7 + 3a_6 + 2a_5 + a_4 + 3
4変数はさすがにヤバいんよ
試しに$ f''(0)=0 を解いてみますか
$ a_4 = -4a_7 - 3a_6 - 2a_5 - 3
$ a_3 = 3a_7 + 2a_6 + a_5 + 4
$ a_2 = 0
これってもしかして無限に片側の$ f^{(n)}(x) = 0にすればそこそこいい感じのカーブできる?
$ a_5 = -3a_7 - 2a_6 - 4
$ a_4 = 2a_7 + a_6 + 5
あ パターン見えたよ
$ a_n = 1-n
$ a_{n-1} = n
あれ
(議論の飛躍)
$ f(x) = (1 + k)x^{k} - k x^{k + 1}
https://gyazo.com/72ae7a9ccab592b5e0a3fd0315d03b6f
これ答えでは???
easeOutは$ 1 - f(1 - x) = 1 + (n - 1)(1 - x)^n - n(1 - x)^{n - 1}
こっちは多項式の形にするのは面倒なので諦めたほうが良い
code:glsl
float easein( float x ) {
float x6 = x * x * x * x * x * x;
return -6.0 * x6 * x + 7.0 * x6;
}
float easeout( float x ) {
return 1.0 - easein( 1.0 - x );
}
同じセオリーで加速度ゼロも
$ m = n - 1
$ a_n = \frac{m^2 - m}{2}
$ a_{n-1} = m^2
$ a_{n-2} = a + m
https://gyazo.com/e1f5712be2a37a0a880d2f80a690717f
いいじゃん