Maya skinning 情報の import/export メモ

## 背景

* Maya の skinning(skinCluter) 情報を, 自前 rigging ツールなどと連携したい.
* FBX などではうまく export/import できない.
* なるべく Maya 標準機能 + 標準的なデータ形式(ASCII, jpg/tiff)だけを使いたい.

http://www.chrisevans3d.com/pub_blog/saveload-skinweights-125x-faster/

## Maya 機能

MAYA HAS TWO WAYS TO EXPORT SKIN WEIGHTS. WHICH DO YOU USE?
https://lesterbanks.com/2016/07/export-import-skin-weights-maya/

### weight map

`Skin` -> `Export weight map`

画像で weight を出力. UV 展開に weight を輝度 or alpha として出力(UV ついていないと自動で Maya が割り当ててくれるのかな?)

### XML weights

`Deform` -> `Export weights...`, `Import weights...`

XML 形式で頂点 weight 情報を export/import

https://help.autodesk.com/cloudhelp/2018/ENU/Maya-Tech-Docs/Commands/deformerWeights.html

Maya 2018.6 で出したサンプルです.

```
<?xml version="1.0"?>
<deformerWeight>
  <headerInfo fileName="skintest.xml" worldMatrix="1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 "/>
  <shape name="pPlaneShape1" group="145" stride="3" size="9" max="9">
    <point index="0" value=" -0.500000 -0.000000 0.500000"/>
    <point index="1" value=" 0.000000 -0.000000 0.500000"/>
    <point index="2" value=" 0.500000 -0.000000 0.500000"/>
    <point index="3" value=" -0.500000 0.000000 0.000000"/>
    <point index="4" value=" 0.000000 0.000000 0.000000"/>
    <point index="5" value=" 0.500000 0.000000 0.000000"/>
    <point index="6" value=" -0.500000 0.000000 -0.500000"/>
    <point index="7" value=" 0.000000 0.000000 -0.500000"/>
    <point index="8" value=" 0.624816 0.000000 -0.804135"/>
  </shape>
  <weights deformer="skinCluster1" source="tip" shape="pPlaneShape1" layer="0" defaultValue="0.000" size="7" max="8">
    <point index="0" value="0.006"/>
    <point index="2" value="0.016"/>
    <point index="3" value="0.009"/>
    <point index="5" value="0.037"/>
    <point index="6" value="0.067"/>
    <point index="7" value="0.035"/>
    <point index="8" value="0.500"/>
  </weights>
  <weights deformer="skinCluster1" source="mid" shape="pPlaneShape1" layer="1" defaultValue="0.000" size="8" max="8">
    <point index="0" value="0.199"/>
    <point index="2" value="0.197"/>
    <point index="3" value="0.495"/>
    <point index="4" value="0.500"/>
    <point index="5" value="0.687"/>
    <point index="6" value="0.474"/>
    <point index="7" value="0.839"/>
    <point index="8" value="0.500"/>
  </weights>
  <weights deformer="skinCluster1" source="root" shape="pPlaneShape1" layer="2" defaultValue="0.000" size="8" max="7">
    <point index="0" value="0.795"/>
    <point index="1" value="1.000"/>
    <point index="2" value="0.787"/>
    <point index="3" value="0.495"/>
    <point index="4" value="0.500"/>
    <point index="5" value="0.277"/>
    <point index="6" value="0.459"/>
    <point index="7" value="0.126"/>
  </weights>
</deformerWeight>
```

xml のフォーマットの仕様が無いので, 推定するしかないのですが,

`index` 頂点番号
`size` : 個数
`shape` の `max` は exclusive だが,  `weights` の `max` は inclusive の模様
(たとえば shape では size=9, max=9 だが最大 index は 8. `tip` では max=8, point index も最大は 8)

weights については, defaultValue(= 0.0)の頂点については省略されている.

のようですね.

## Skeleton(deformer) 構成

Maya 標準機能では, 頂点ごとの weight 情報のみ import/export できるようなので, skin(skeleton)や deformer の構造も欲しい場合は別途 python などで export/import が必要.

* skinIO : https://github.com/cedricB/skinIO

が参考になるかも?

もしくは, Maya ASCII(mel)を頑張って解析する.
(単にジョイントの位置と回転くらいなら, こちらのほうが手っ取りばやそう)

https://github.com/syoyo/maya-scenefile-parser

パースだけですが, setAttr `double3`, `matrix` 対応しました.

## .ma から頑張って weight をパースする

Maya 2018 から出した .ma には以下のような感じで weight が保存されています.

```
	setAttr ".wl[671:867].w"
		2 26 0.0040794747214958254 27 0.99592052435547518
		3 25 3.2356118185617889e-09 26 0.023064160085259508 27 0.97693583667912887
		3 25 7.2918962586085041e-10 26 0.016902171672574018 27 0.98309782759127029
		3 25 2.084342230892521e-10 26 0.011013674489993465 27 0.98898632528375363
		2 31 0.011205626645190868 32 0.98879437328416786
		3 30 1.0635849062488488e-10 31 0.012923130011588516 32 0.98707686988165211
                ...
```

`wl[X:Y].w` で頂点範囲 X から Y までの weight を設定. 最初が (joint, ウェイト) ペアの個数

```
N joint_id0 weight0 joint_id1 weight1 ...
```

Maya が出す .ma に対しては, ウェイト情報は改行が入っていているので, パースしやすそうです.

ただ, weight をプロシージャルな方法で割り当てている場合(e.g. ミラーリングとか)はそのままでは使えないかもです.

(同様の問題が, UV 情報を .ma から読むときに発生する. たとえば plane の UV 値が欲しいばあい, Maya(.ma)では UV 自動生成してから,  UV をいじったところは, uvTweaker で保存なので, いじったところの UV しか取得できない & dependency graph 的なのを評価しないといけない)

また, setAttr で weight 設定のフォーマットは, MAYA_DISABLE_PACKED_MULTI_ATTRIBUTES 環境変数により, 仕様が変わるかもしれません.

https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/JPN/Maya-EnvVar/files/GUID-FC154DF1-CC21-4DBF-9FAC-19FDE6DCBC9A-htm.html

## その他

* SAVE/LOAD SKINWEIGHTS 125X FASTER http://www.chrisevans3d.com/pub_blog/saveload-skinweights-125x-faster/
* Chronicles of CedricK: escape from Pymel Bay(skinIO) https://circecharacterworks.wordpress.com/2016/10/06/chronicles-of-cedrick-escape-from-pymel-bay/
* maya-skinning-tools https://github.com/robertjoosten/maya-skinning-tools
* brSmoothWeights & brTransferWeights https://github.com/IngoClemens/brSmoothWeights
* OnionSkinRenderer 1.1 Release video(ghosting 表示?) https://vimeo.com/259565212

## TODO

* [ ] 商用でもよいのでいい感じの skinning import/export 機能を持つツールがあるか調べる 
* [ ] skin/deformer を Maya ASCII で出力し, 頑張って自前パースする(https://github.com/mottosso/maya-scenefile-parser 参考)