クロスシミュレーションの実験
こんにちは。ランカース社内ライブラリ開発研究部です。
社内ライブラリでは実験的に新機能を実装しているのですが、昨年のCEDEC2024の講演「『鉄拳8』の揺れ物表現を支えた内製クロスシミュレーション」に影響を受けて、クロスシミュレーションの実装を検証中です。
実装してみてわかったことを備忘録として残しておきます。
計算方法
クロスシミュレーションの計算には主に2つの方法があるようです。
- オイラー法: 速度を先に求めてから位置を計算する
- ベルレ法: 座標を先に決め、相対位置の移動量から速度を求める
プログラム的には「ベルレ法」が優れているので、こちらを採用しました。
座標の計算
座標を計算する際には、以下の式を使用しました。
vec3 f; // 力
float m; // 質量
vec3 a = f / m; // 加速度
vec3 p; // 位置
vec3 v; // 速度
vec3 delta; // 更新にかかった時間
vec3 new_p = p + v * delta + 0.5 * a * delta * delta; // 新しい位置
この式は、現在の位置、速度、加速度を考慮して新しい位置を計算します。
制約(バネ)の計算
制約の計算には、フックの法則を使用します。
float f; // バネの力
float k; // バネ定数(バネの強度)
float rest; // バネの自然長
float d; // 現在のバネの長さ
f = (d - rest) * -k; // バネの力
この式は、バネが伸び縮みする力が働くことを表現しています。
ウェイト付けと計算用メッシュ
ウェイト付けには以下の方法で行いました。
- 一枚板の計算用のスキニング設定されたメッシュを使用
- 頂点カラーがウェイトとして機能
- メッシュ分割数がそのままノードになる
- 表示メッシュは計算メッシュ頂点からの距離でバインド
Maya上でウェイト付けしたものをそのまま計算に使用できるため、専用のエディタを作成する必要はないかもしれません。
クロス処理の流れ
- スキニングアニメーションによる動きを各頂点に加算し前フレームからのDeltaの計算
- 各頂点間の距離を元の距離になるように伸縮を加減算
- モデルにめり込んでしまっている頂点を押し出す
- 「2」と「3」を1フレーム内で n回繰り返す (この回数が少ないと振動が発生してしまう)
- 計算用メッシュの位置が決まったので、事前に計算してあるウェイトに従い表示用メッシュの位置を算出する
このプロセスにより、クロスシミュレーションの自然な動きと柔軟性を作ることができました。
参考資料
その他、参考にした資料は以下のものがあります。
- WebGLで布シミュレーションを実装してみる:CPU上での処理ですが、全体の流れはこれが一番わかりやすいです
- 『ストリートファイター6』の世界に生命を!~物理シミュレーションを活かしたアニメ物理~:CEDEC2024の公演をCGWORLDさんがまとめたもの
- 『鉄拳8』の揺れ物表現を支えた内製クロスシミュレーション:CEDEC2024の公演のプレゼン資料です。理想はこれですね。GPGPUでの処理の参考になりそうです