Maya リギング/アニメーション情報 を glTF 2.0 に変換するメモ

# 背景

Maya で rigging/animation がついたデータを, glTF 2.0 に変換し, 自前レンダリングエンジンとかで再生したい.

とくにキャラクター系. skinCluter と blendShapes に対応は必須.


## Maya での rigging/animation


### 用語

* cluster : Maya の場合は複数頂点や複数オブジェクト(= group の意味合いに近い?)を指しているっぽい.
* skin, skinning : joint, skeleton などでメッシュを変形させること?
* joint : joint(制御点) 
* bone : joint で構成される線分. https://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/MayaLT-CharacterAnimation/files/GUID-1B59334F-2605-44C3-B584-A55B239A2CBE-htm.html
* skelton : bone のグループ? https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-906B71D3-C153-4880-A8EF-F9A6D1AE4AD5-htm.html
* bindSkin : メッシュを joint/skelton で剛体変形させる. 
* skinCluster : メッシュを頂点単位で joint/skelton で変形させる. vertex skinning 
* deformer : 変形させるもの
  * sculpt deformer 球を動かすとメッシュが sculpt ツールでのように変形する https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2019/ENU/Maya-CharacterAnimation/files/GUID-8A7188B9-34C1-48B8-B690-5CB0EA36932D-htm.html   
  * lattice deformer : 制御格子でメッシュを変形 https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-8F27AC88-6892-4EAE-A1CB-C43FADF95A64-htm.html
  * cluster deformer https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-B7C96FEA-C415-4927-8E02-396F0E837DE2-htm.html
  * wrap deformer https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-B98E74F5-6965-41B1-BBF8-471FB2FAD7EC-htm.html
  * delta mush
  * ほかにもいろいろ
* Muscle : muscle シミュレーションできる? 内部的には skinCluster とかでの実装になっているのかしら? https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-90B5E302-8DAA-4780-BCD6-FB9C60FF9E05-htm.html

他にもいろいろ機能はあるが, glTF とかに変形できそうなのを考慮すると上記程度でしょうか.

## bindSkin

メッシュに bone をバインドする. 剛体変換用

## skinCluter

ボーンをメッシュにバインドし, smooth skinning できるようにする.
リアルタイムグラフィックスでいう vertex skinning と同等.

メッシュ(オブジェクト)単位で剛体変換ではなくて, 頂点単位で変形できるようにするのが skinCluter らしい. 
各頂点ごとにボーンに対するウェイト(影響力)を持つので, ボーンの数が増えるとデータサイズは大きくなりそう.

## Maya cluster deformer

https://www.youtube.com/watch?v=Bvq7CE7_EN4

頂点に対して, cluster handle(`c` の文字)の translate, rotate, scale を, mesh vertex に与える.
`envelope` 影響力の強さ?

頂点ごと影響力の範囲や強さは weight paint で対応できる模様.

### 描画エンジンでの対応

ふるまい自体は単純っぽいので, 自前で実装しての対応もありえる.
glTF skin の範囲でやるのであれば, cluster handle を joint に変換して, 各 vertex の weight を調整すればいけるか? 

=> Bake deformer である程度 Maya でやってくれるかも?

https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-8B68FF4A-E9BC-44E9-B0D9-53CFE0C008FC-htm.html

## wrap deformer

proxy deformer のようなもの?

skinning に適用すると, これは wrap skinning とも呼ばれる.

https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-56B2CCA5-25C6-47FD-BA98-7F3AC91D4B22-htm.html

skelton -> wrap(mesh/object) -> mesh

とすることで, より細かい skinning 制御が行える.

実装としては cluster deformer で cluster handle が wrap mesh　の頂点で行う感じかしら?

Blender には似たような機能で wrap modifier があるのでこの実装が参考になるかも.

https://docs.blender.org/manual/en/latest/modeling/modifiers/deform/warp.html

Maya bake deformer で変換できるとよいところ.

もしくは, wrap deformer から skinCluster に変換する Mel スクリプトを参考にするとよいか.
https://gist.github.com/SEVEZ/6182539b1c7ba3a98635


## delta mush

Delta mush: smoothing deformations while preserving detail
https://dl.acm.org/citation.cfm?id=2614144&dl=ACM&coll=DL

が Maya に実装されている.

Blender での実装(昔?)
https://developer.blender.org/T43988

Delta mush から smooth(?) skinning への変換ツールあります. Maya 2016 なので最新版では書き直しが必要.

https://vimeo.com/181910645

## glTF での animation 対応

glTF では (vertex)skinning と morph(blend shapes)に対応している.

したがって Maya skinCluster を glTF skin に変換することで対応可能(細かいところでは scale 行列とか pivot とかうまく変換しずらいところがあるかも).

Maya blendShapes はこれも そのまま morph に変換.

glTF では skin と blendShapes の混在は可能であるが, 仕様がややこしいので, exporter と player の実装がに注意. https://qiita.com/syoyo/items/236f2a4713aa381c6735

#### glTF での deformer

deformer は無い. 実装が簡単なものなら, extra 情報として glTF に書き出し, 描画エンジン側で対応する感じになります.

#### skin と morph の評価順

glTF では, morph してから skinning の模様.

skinning してから morph したい場合はどうしたらいいかしらん?
 
### Sparse accessor

頂点ごとに全ての bone の weight を持つとデータ量が多くなる. 影響しないところはデータを省きたい.
たとえばボディが一つのメッシュでできていて, 右腕を動かすボーンは左腕には影響しない.

glTF の sparse accessor が skinning に使えないか検討する.  
blendshapes では sparse accessor を利用可能(実装側での対応次第)

sparse accessor が使えない場合は, vertex ごとに joint の個数を可変にできたりしないだろうか?

メッシュの頂点を joint の影響力ごとに分割するという手もあるが, なるべくこの方法は避けたい.

### Skin weight の正規化

glTF では正規化されているものと仮定している
https://github.com/KhronosGroup/glTF/issues/1213

Maya では正規化されていないかもしれない.

## Maya skinCluter を skin に変換する.

Maya2GLTF や Orge3D の exporter 参照.

glTF の仕様では, 4 要素単位なので, 4 個以上 bone 影響のある場合は set をつくる(`JOINT_0`, `JOINT_1`, ...)

https://github.com/KhronosGroup/glTF/issues/878

https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skinned-mesh-attributes

## Maya BlendShapes を morph に変換する

Maya2GLTF や Orge3D の exporter 参照.

## deformer

Deformer については, glTF の仕様にはないので, 自分で再現処理しないといけない.
lattice deformer とかは実装しやすそう.
sculpt deformer は Maya の振る舞いがわからないとちょっと難しいかも(Blender の sculpt ツールのソースコードが参考になるかも?)

## 回転の値について

glTF では quaternion しかサポートしていない. 出力された glTF をあとでいじって回転をちょっと変えたいときなど euler 回転を extra で出力しておくなどしておくとよさそう.

## 他の Maya skinning 方法

https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-CharacterAnimation/files/GUID-EFE68C08-9ADA-4355-8203-5D1D109DCC82-htm.html

## TODO

* [ ] Maya で deformer による変形を bake させてどこまで glTF skin/morph の枠組みでできるか調べる
* [ ] Maya muscle について調べる

## 参考文献

* https://github.com/WonderMediaProductions/Maya2glTF
* https://github.com/OGRECave/ogre/blob/master/Tools/MayaExport/src/skeleton.cpp