3次ベジェ曲線によるイージング実装メモ
単射にするには制御点のx値に制限が必要。
c0.x <= c1.x <= c3.x
、c0.x <= c2.x <= c3.x
単調にしたい場合はy値にも同様の範囲制限が必要。確実に0 ~ 1
範囲に収めたいときなどに。
肝心のベジェ曲線からy = f(x)
というイージングを求めるには3次方程式を解くしかなさそう。媒介変数にx
入れたらいいのかと思いきや媒介なのでx
軸とは対応していない。
単射という条件のもとで簡易な解法ないものか。
人気のありそうなパッケージ。関連情報色々書いてくれている。
このリンクにもあるようにfirefoxなども3次方程式から解いているらしいのでやはり抜け道はなさそう。
自作にこだわらず上のパッケージに頼ってしまうのがよさそう。中身もかなり軽量化されている。
ベジェ曲線は描画と制御は簡易だがイージング関数としては実は高コスト。
Unityではベジェ曲線代替?にCubic Hermite Splineという方法を使っているらしい(下記サイトからの2次情報)。
UE4のイージング情報。
やはり汎用的なベジェではなくある程度形状の決まったイージングを用意しておくのが主流か。
しかしBlenderではベジェイージングがデフォルトになっている。
Blenderでのベジェイージング本命はこの辺か。
イージングはフレーム単位に離散であるから、ベジェを離散に分割して漸近的にイージング値を求めているっぽい?
BKE_curve_forward_diff_bezier
という関数の実装はここ。
ベジェ上を漸近的にステップしている。
上の理論これっぽい。
いやこれよく読むとやっぱり媒介変数t
について数列で求めていく手法ではないか。
そしてこの関数はキーフレームの補間に使われていそうな気配がない。
やはり抜け道はなさそう。ゲームエンジンが積極的に使っていないことが証拠だろう。
イージング系ライブラリだと始点と終点の比率を扱うため、2点の値を同じにしての変形ができない。
そもそも求めているものが0 => 1
へ向かうイージングではなかったのか。分からなくなってきた。
解くしかない。
X(t) = X0
をt
について解いて、Y(t)
を求める。
X(t) - X0 = 0
の方程式はこのあたり。Y(t)
も形は同様。
解き方参考サイト。
冒頭の条件を満たしているベジェ曲線から求めた3次方程式なら必ず実数解が1つと虚数解2つ
or 3重解
の場合になってくれる。なってくれないならどこかがおかしい。
冒頭の条件は0 <= t <= 1
の範囲内に解がただ1つあることを保証しているだけ。
全ケースを巡って実数解を求め、そのうち範囲内に収まっているものを採用しないといけない。
① p=q=0:実数解1個(3重解)の場合
② D>0:実数解1個 虚数解2個の場合
③ D=0(p≠0またはq≠0):実数解2個(2重解)の場合
④ D<0:実数解3個の場合
というわけでベジェ曲線専用3次方程式の解という名目で実装。
おっけい。
落着と思いきやエラーが起きてしまった。
このケースも考えなくてはいけないかもしれない。
④ D<0:実数解3個の場合
冒頭の条件だと0 <= t <= 1
の区間でのみt -> x
を単射にできる。
つまりX(t) - X0 = 0
の解となるt
はその区間外なら複数個あっても不思議はない。
こんどこそ
いけてそう。エッジケースまだ残ってたら使ってればそのうち見つかるだろう。
③ D=0(p≠0またはq≠0):実数解2個(2重解)の場合
必要と書いておきながらこのケースを除外したままだった。追加実装。
幾何的な操作をしているとゼロ近傍除算がどうしてもでてくる...!
どうもまだエラーが出ると思ったら、2次関数に落ちる場合の処理が実数解を1つだけ求めればいいと思っていたときのままだった。ファイナルラストアンサー。