Mesh Bake の実装
Mesh Bake とは
Unity にはその名もずばり BakeMesh という関数があります。
SkinnedMeshRenderer-BakeMesh - Unity スクリプトリファレンス
SkinnedMesh で bone を動かしてからこの関数を呼ぶと、その状態の mesh を得ることができます。
Bake と Mesh.bindposes
bake された Mesh を SkinnedMeshRenderer で動かすには、 bake した状態の bone から Mesh.bindposes を計算して置き換える必要があります。 以下のコードでできます。
SkinnedMeshRenderer smr;
mesh.bindposes = smr.bones.Select(x => x.worldToLocalMatrix).ToArray();
逆に言うとこの計算で得られる値と異なる bindposes には、 なんからの mesh 変形が含まれています。
- scaling, mirrorring … etc
- A スタンスの T スタンスへの補正
- Z-UP を Y-UP に回転
例えば、mirror を表現する負のスケーリングをクリアする効果があります。
mesh が反転して格納されていて、bondpose でミラーリングする手法があった。
bindposes の変更
bone の world 位置を維持して回転と拡大縮小を変更してから bindposes を計算した場合でも、 Skinning が壊れることはありません。
任意の流儀の rig に合わせられます。
lossyScale と同じ問題があり、行列では表現できるが scale では表現できないなどのトラブルがあります。
blendshape に対応する
blendshape を列挙してひとつずつ weight を上げてから bake して、 元の mesh の vertices を引き算することで blendshape の bake を得ることができます。
Assets\UniGLTF\Runtime\MeshUtility\MeshFreezer.cs
vrm-0.x 正規化
BakeMesh に対する boneposes 計算前に回転と拡大縮小を変更することが可能であることを利用して、 無回転、無拡大縮小にするのが vrm-0.x の正規化処理です。 事前に T-Pose にするという規約が追加されています。
Assets\UniGLTF\Runtime\MeshUtility\MeshFreezer.cs