Physics
WMMDの物理:1つのインターフェースの背後に3つのバックエンド
MMD忠実な基準としてのBullet、純Rustのフォールバック、クリーンルームのPGSソルバー、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を切るモーションも、作られたとおりに再生されます。
どう確かめているか
物理の正しさは目視で決めません。ツールクレートには、スナップショットランナーと並んで物理検証器があります。
エンジン全体の作業規則は「修正は一般化しなければならない」です。問題を露呈させたモデルで再現するのは構いません。ただしコミットする変更と追加するテストは、一般的な言葉で書きます。任意のボーン数、モーフ集合、マテリアル構成、リグ配置に対して成り立つ形で。特定のファイル向けの特別扱いにはしません。