ひとことで
キャラクターの皮膚(頂点)を骨に合わせて動かすスキニングで、複数の骨の動きを「回転と平行移動をまとめた量(デュアルクォータニオン)」のまま混ぜる方法です。一般的な線形ブレンドスキニング(LBS)は、骨の変換行列を重みで平均するため、関節を大きくねじったり曲げたりすると、関節がつぶれて細くなります(キャンディの包み紙現象)。DQS は、混ぜた結果が常に剛体の変換になるので、ねじっても太さが保たれます。
ゲームでの使いどころ
- 肩・手首・前腕のねじれ:腕を大きくひねったとき、手首の周りが細くつぶれるのを防ぐ。
- 肩や股関節の大きな回転:体積が減って見える関節を自然にする。
- エンジンの選択肢:Unity・Unreal・Maya などに DQS の選択肢がある。GPU の頂点シェーダーでの計算量は LBS とあまり変わらない。
- LBS との使い分け:DQS は曲げたときに関節の外側がふくらむ傾向があるので、骨ごとに LBS と DQS を混ぜる、ねじり用の補助骨を入れる、などと組み合わせる。
しくみ
線形ブレンド(LBS) では、骨 の変換(行列) と重み で、
とします。2 本の骨が同じ軸で 180° ずれてねじれていると、関節の途中の頂点は「一方で動かした位置」と「円柱の反対側へ動かした位置」の平均になり、中心へ寄ってつぶれます。行列の平均は、もう回転行列ではない(縮小を含む)からです。
デュアルクォータニオン は、回転 (単位クォータニオン)と平行移動 を
でまとめたものです()。DQS では、
と重みで足してから正規化し、1 つの剛体変換として頂点に当てます。平行移動は で取り出します。正規化した結果は必ず「回転 + 平行移動」なので、縮みが起きません。
実装のポイント
- 符号をそろえる:クォータニオン と は同じ回転を表します。符号の違うものを足すと打ち消し合うので、最初の骨と内積が負なら符号を反転してから足します。
- CPU では 1 回だけ変換:骨ごとのデュアルクォータニオンは、毎フレーム骨の行列から CPU で作り、シェーダーに渡します。
- 拡大縮小は扱えない:デュアルクォータニオンは回転と平行移動しか表せません。骨に拡大縮小があるなら、別に処理する必要があります。
- 法線も同じ変換で:法線は回転部分だけで回します。LBS のように逆転置行列を作る必要がありません。
つまずきやすい点
- 曲げたときのふくらみ:DQS は、関節を大きく曲げると外側がふくらむ(膝や肘が出っ張る)傾向があります。関節の種類によって LBS と使い分けます。
- 重みを混ぜる幅:重みが関節のごく近くで急に切り替わると、どちらの方法でも関節がかくっと折れます。適度な幅で混ぜます。
- 180° を超えるねじり:デュアルクォータニオンの補間は最短の回転を選ぶので、180° を超えるねじりは逆向きに解釈されます。極端なねじりには補助骨を入れます。
デモで試すこと
- 上の腕(LBS)は、ねじりが大きくなると関節がつぶれて細くなります。下の腕(DQS)は、同じねじりでも太さが保たれます。数値の「関節の細さ」を比べてください。
- 「自動で動かす」を切り、「ねじり」を 0 から 180 まで動かすと、LBS の関節が 180° 近くでほぼ点までつぶれることがわかります。
- 「曲げ」だけを大きくすると、LBS では関節の内側がつぶれ、DQS では外側が少しふくらみます。
- 「重みを混ぜる幅」を小さくすると、どちらも関節がかくっと折れ、大きくするとなだらかになります。