レジデント準備完了 静的コンパニオン
kari_mikumao 研究室

Physics

WMMDの物理:1つのインターフェースの背後に3つのバックエンド

MMD忠実な基準としてのBullet、純Rustのフォールバック、クリーンルームのPGSソルバー、XPBDの布エンジン - コンパイル時に差し替えられます。

  • wmmd
  • 物理
  • bullet
  • xpbd

MMDの物理は、シミュレーションの問題である前に互換性の問題です。

揺れもの、剛体、ジョイントは元のツール向けに作られていて、期待される挙動があります。こちらが「正しく」しかし違う形でシミュレートすると、モデルを作った本人にはやはり間違って見えます。そして、それは向こうが正しいです。仕様はこちらのソルバーではなく、あちらのリグのほうです。

なのでWMMDは、複数のバックエンドを1つのインターフェースの背後に置き、そのうち1つを基準として扱っています。

バックエンド

4つはすべてwmmd-runtimeのCargoフィーチャの背後にあり、ホストはコンパイル時にトレードオフを選べます。

  • Bullet(既定) - crates/wmmd-bullet-sysの薄いCシムを介したBullet3による、MMD忠実な基準挙動。ベンダーされたソースをビルドするので、cmakeとC++17ツールチェーンをビルド時に要求します。
  • ネイティブRust - cmakeを必要としない組み込みバックエンド。C++ビルドが割に合わない環境向けです。
  • ネイティブPGS - Havok風のクリーンルーム実装による投影ガウス・ザイデル法とBaumgarte安定化。
  • Loom - 布と髪を狙った実験的なXPBDエンジン。

やってみて分かったのは、最速の実装を持つことより、基準になる実装を持つことのほうが効くということでした。

別のソルバーでリグの挙動が怪しいとき、Bulletの結果が裁定者になります。問いは「どちらが正しいか」ではなく「なぜこのバックエンドは食い違うのか」になります。前者の問いには答えがなく、夜がまるごと溶けます。

ランタイムが持つもの

物理モジュールはIKソルバーやPhysicsControllerとともにwmmd-runtimeの中にあり、PMXの揺れもの拘束をフォーマットの3つのモードすべてで扱います。

ランタイムは不変条件によりCPUのみで、ファイルを読みません。解析済みアセットを受け取り、ホストのフレーム時間に駆動されて、1回のupdate()で物理・ボーン変換・IKを進めます。

物理はモデル追加と同じコマンドキューを通じて、一時停止・再開・リセット・段階指定ができます。細かい話に聞こえますが、エディタではここが推測と診断の分かれ目です。リグを凍らせて再実行できれば、何が起きているのかを実際に見られます。

IKソルバーはVMDのIK on/offトラックに対応しています。シーケンスの一部で意図的にIKを切るモーションも、作られたとおりに再生されます。

どう確かめているか

物理の正しさは目視で決めません。ツールクレートには、スナップショットランナーと並んで物理検証器があります。

エンジン全体の作業規則は「修正は一般化しなければならない」です。問題を露呈させたモデルで再現するのは構いません。ただしコミットする変更と追加するテストは、一般的な言葉で書きます。任意のボーン数、モーフ集合、マテリアル構成、リグ配置に対して成り立つ形で。特定のファイル向けの特別扱いにはしません。