wacchoz’s note

プログラミングとか数学について

スキニングの話(1)

どうせ暇だしスキニングについて書いてみる。

スキニングとは3Dアニメーションで使われる手法で、ポリゴン内部にボーンを仕込んでおき、ボーンを動かすことでポリゴンを変形させる手法である。

骨格構造はジョイント(関節)の集合である。
そしてジョイントとは単なる点ではなく、ジョイントを原点とする座標系を意味すると考えたほうがよい。それぞれのジョイントにxyz座標系があるわけだ。
各ポリゴンはそれぞれのジョイント(で定義される座標系)からどれだけ影響されているかという重みを与えられている。
ではボーンは何かというと、親子関係のあるジョイント間を線で結んだだけのものである。人間にとってわかりやすくするための便宜上のものといえる。

f:id:wacchoz:20181108230226p:plain:w360

まず初期姿勢(rest pose)で考えよう。
両手を左右に伸ばして立っているあの姿勢である。

M_{10}でジョイントj_1を原点とする座標系からモデル空間へ変換行列を表すことにする。
たとえばj_1を原点とする座標系の原点は、モデル空間での座標は、M_{10}\times (0,0,0,1)^Tで表すことができる。

同様に、M_{21}でジョイントj_2を原点とする座標系からジョイントj_1を原点とする座標系に変換する行列としよう。

ジョイントは親から順に1, 2, 3,\dots , kと繋がっているとすると、ジョイントj_kを原点とする座標系をモデル空間に変換する行列は、

\displaystyle M_{k0}=M_{k,k-1}\times\dots\times M_{21}\times M_{10}

と書ける。 またモデル空間からジョイントj_kを原点とする座標系への変換は、この行列の逆行列であり、

\displaystyle M_{0k}=M_{k0}{}^{-1}

と書ける。


さてアニメーションとは、 M_{k0}を時刻tによって刻々と変化させていくことに他ならない。

行列Mは初期姿勢のときの行列として用いたため、アニメーションにより変化したときの行列はBで表すことにしよう。

時刻tでのジョイントj_kからモデル空間への変換行列をB_{k0}(t)とする。

同様に

\displaystyle B_{k0}(t)=B_{k,k-1}(t)\times\dots\times B_{21}(t)\times B_{10}(t)

である。

ある初期姿勢でのメッシュ上の点vがジョイントj_kにのみ影響されているとしよう。

このとき点 \mathbf{v}の、ジョイントj_kを原点とする座標系での座標は、M_{k0}{}^{-1} \mathbf{v} となる。

この点を時刻tでのモデル空間での座標に変換すると、

\displaystyle v' = B_{k0}(t)\times M_{k0}{}^{-1}\times \mathbf{v}

となる。これがボーンアニメーションの基本である。
しばしば C_{k}(t) = B_{k0}(t) \times M_{k0}{}^{-1}とまとめて書かれることもある。

ここまでは点\mathbf{v}がジョイントj_kのみに影響されるとしてきたが、複数のジョイントに影響される場合も同様であり、ジョイントj_{k1}, j_{k2}, \dots, j_{kn}にそれぞれ重み w1, w2, \dots , wnで影響されるとした場合、

 \displaystyle \mathbf{v'}=\sum_{i=1}^n w_i B_{ki,0}(t)M_{ki,0}{}^{-1}\mathbf{v}

とする方法がLinear Blend Skinningである。 この方法は広く用いられ、そしてしばしば問題を引き起こす。(つづく)