魔改造イージング関数

こちらのチートシートを参考にします。

イージングはアニメーションで使用されるのが主だと思われますが、世の中には関数の形に劣情を催す変態がいるのでその人ら用です。

まず関数の形を簡単に表示できるようにしておきます。

import java.util.List;

List<Float> glist = new ArrayList<Float>();
interface IEaseFunc
{
    float exe(float x);
}
IEaseFunc func;

void setup()
{
    size(500,500);
    
    func = (x->easeInSineTrip(x));//ここの関数を入れ替えて使います。
      
    for(int i = 0; i<width; i++)
    {
      var g = func.exe(map(i,0,width,0,1));  
      glist.add(g*height/2);     
    }
}

void draw()
{
    background(255);
    for(int i = 0; i<glist.size(); i++)
    {
      line(i,0,i,glist.get(i));
    }
}

試しにeaseInSine関数をパクります。

static float easeInSine(float x){return 1 - cos((x * PI) / 2);}

結果
図は下にプラス

画像1

だいたいOKです。

入力パラメータをいじってみます。

var g = func.exe(map(i,0,width,-3,3));  

画像2

var g = func.exe(map(i,0,width,0,2));  

画像3

ははぁ、なるほど。

良く分かりませんがeaseInSine関数はSin関数を途中でちょん切ってるのが良く分かります。


easeInSine関数の入力値xは0から1ですので、
(1-x)にして反転させてみましょう。

static float easeInSineInv(float x){return 1 - cos(((1-x) * PI) / 2);}

画像4

反転した。

張り合わせてみます。

static float easeInSineTrip(float x)
{
 if(x<0.5)
 {
   return easeInSine(x*2);    
 }
 else
 {
   return easeInSineInv((x-0.5)*2); 
 }  
}

画像5


easeInOutQuart関数をパクってみます。

static float easeInOutQuart(float x)
{
 return x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2;
}

画像6

反転させて

static float easeInOutQuartInv(float x){ return easeInOutQuart(1-x);}

画像7

はっつけて

static float easeInOutQuartTrip(float x)
{
 return x<0.5 ? easeInOutQuart(x*2) : easeInOutQuartInv((x-0.5)*2); 
}

画像8


Sinの場合

土台となっているsin,cos関数を観察してみましょう。

sin,cosの入力は0-2PI、出力は-1から+1
それを0-1入力のsin,cosに変換したければ単純に2PIに対して入力値(0-1)を乗じます。

static float Sin(float x){return sin(x*2*PI);}

図は下にプラス
ゆえに出力は0,+1,0,-1,0

画像9


出力値をマイナスにした場合

static float Sin1(float x){return -sin(x*2*PI);}

図は下にプラス
ゆえに出力は0,-1,0,+1,0

画像11


入力値をマイナスにした場合

static float Sin2(float x){return sin((-x)*2*PI);}

図は下にプラス
出力値マイナスと同じ

画像12


入力値を1を基準に反転

static float Sin7(float x){return sin((1-x)*2*PI);}

画像16

出力値を1を基準に反転

static float Sin8(float x){return 1-sin(x*2*PI);}

途中まで逆回転、途中から振幅倍の順回転
出力は1,0,1,2,0

画像17

全体

画像18


入力を倍、周波数倍にした上で全体を見ると

static float Sin9(float x){return 1-sin((x*2)*2*PI);}

出力は1,0,2,0,2,1
負にならない。マイナスの山が全てプラスに乗っているのが分かります。

画像19


入力値を2倍にした場合

static float Sin3(float x){return sin((x*2)*2*PI);}

倍速、波の1周が早くなる。周波数高くなる。

画像13

入力値半分の場合

static float Sin4(float x){return sin((x/2)*2*PI);}

速度半分

画像15

出力値2倍の場合

static float Sin5(float x){return 2*sin(x*2*PI);}

波の高さ(振幅)が倍になる。

画像14


Cosの場合

static float Cos(float x){return cos(x*2*PI);}

図は下にプラス
sinからPI/2ずれる。

画像10

これはSinにPI/2(90度)足したものと同じ。
位相が進んだといわれるやつです。波目線で見るとCos波はSin波の途中から始まってます。

static float Cos2(float x){return sin(x*2*PI+(PI/2));}

画像21



以上をふまえて

easeInSine関数は周波数(波の1周の速さ)半分で振幅(高さ)倍で負にならんことがわかります。あと、Cosにしてるのは位相を遅らせているのでしょう。Sin波をちょっと巻き戻しているわけです。


以上のことから、easeInSine関数というのはSin波にこれから突入するよ関数であることが明らかになりました。

static float easeInSine(float x){return 1 - cos((x * PI) / 2);}

ところで魔改造メタボールではパラメータに減衰率をとり、関数の影響力を早期に爆散させることができました。つまり早期に爆散させれば関数の影響は領域の局地的部分のみにとどまり、爆散させなければ関数の影響は領域の全体にのったりと圧し掛かります。

同じことを試みます。

早期に爆散させることができるeaseInSine関数の逆の関数。

static float easeInSineInv2(float x, float a)
{
 if(x<=0.5)
 {
   return 1 - cos(((1-x) * PI - PI / 2) / 2 * a);
 }
 else
 {
   return 0;
 }
}


画像20

この関数はメタボールに利用できるはずです。今度試してみます。

この記事が気に入ったらサポートをしてみませんか?