■ここまでのまとめ
カーブのエディタを作ろうと、C#で着手。
目標としているのは XSI ModToolにあるようなカーブエディタです。
しかしながら、エルミートスプライン、ベジェ曲線等試すも、カーブの形状すら違っていた。
上記のベジェ曲線を3次のものに変更したところ、思うような曲線が書けるようになった。
確かに作図する上で3次のベジェ曲線を使えばやりたいことは出来るような感じである。
■必要条件
カーブの制御点の情報は、位置(t,v)、そして接線情報である。
「ゲームプログラマになる前に覚えておきたい技術」の3次補間のケースでは、
制御点での接線情報に若干不足がある。
制御点での傾き情報は与えられるが、その影響持続時間に関する情報を設定できない。
そのため、接線情報を設定できるパラメトリック曲線の方法を選ぶ必要がある。
今回候補とする曲線種類
- エルミート曲線
- ベジェ曲線
■任意の時刻における値を調べる
これら曲線を使えばやりたいことが出来そうではある。
しかし、これら曲線では区間内の平面上の任意の点を媒介変数を使用して表現する。
つまり、横軸がいくついくつのときの、縦軸の値は?という問題に答えることができない。
今回の目標がカーブエディタであるということは、
横軸の値に対して、縦軸の値は1つだけを持つべきである。
横軸変数 x とし、縦軸変数 y とするならば、y は x の一価関数でなければならない。
つまり y = f(x), あるxにおけるyの値は一意に定まらなくてはならない。
XY平面上で曲線がループを描いてしまってはいけない。
一般的に解説されている曲線の書き方では媒介変数の値を与えることで、
2点間で補間された点を求めて点を打つ。
このとき、XとYそれぞれで曲線の補間式が計算される。
今横軸Xを時刻として扱うことを考えているので、このXが求まっている状態から、
Yを求めることが必要である。
このXとYを関連づけているのは媒介変数であるので、
求まっているXから媒介変数の値を求め、それから Y を求めることが出来る。
- 曲線の関数 f()とする.
- 媒介変数 s = f'(X);
- 目的の値を求める. Y = f( s );
回り道をしているようだけど、これで任意の横軸値から縦軸の値を算出できる。
■計算方法について
実は曲線の式は、3次方程式である。
よって、この3次方程式の解を導き出せばいいという問題に変わる。
具体的には
曲線は f(x) = A * x^3 + B * x^2 + C * x + D なので、
t0 = A * x^3 + B * x^2 + C * x + D
式変形して
A * x^3 + B * x^2 + C * x + D – t0 = 0
を満たす x を求めることなる。
■結果
今回はエルミート補間を試してみた。
自分で実装したのは、任意のX座標を引数としてそのときのYを得るという、
今までに説明した方法である。
一方、比較のためにD3DXで用意されているD3DXVec3Hermite関数で計算した
曲線も表示させてみた。
左側の曲線が自前で処理しているものである。
- 曲線1:黄色
- 曲線2:緑
右側の曲線はD3DXを用いて媒介変数を0から1へと変化させ、
そのとき得られたXY座標値でグラフ化したものである。
若干ズレも見えるが、そこまで大きく両者にズレはないし
今回の目的は達成したと言える。
■追記
同じようなことをしている人を発見しました。
”Zで行こう!”の9月の日記にてベジェ版でやっているようです。
アドレス:http://blog.livedoor.jp/take_z_ultima/archives/2010-09.html?p=4
同じような結論へとたどったようなので、この方法も間違ってはいないのかなとおもいました。