Maya2022のUSDを触ってみよう - いろいろExportする

6 min read読了の目安(約5700字

通常のExport SelectionなどからExportする場合だけだと
AddAttributeしたアトリビュートは出てこないし、USD関連の各種設定も出力できないというので
かなり物足りない感じでした。
さすがにできるだろう...という気がしたので、詳しく調べたらできたので
やり方をまとめてみようとおもいます。

PythonでExportする

GUIの設定からだとできることは限定的で、
細かく調整したい場合はスクリプトから実行する必要があります。

Helpは こちらのHelpを参考にします。

Exportするには mayaUSDExport を利用します。

import maya.cmds as cmds

exportPath = "D:/test.usda"
cmds.mayaUSDExport(file=exportPath, selection=True)

とりあえず、Exportしたい場合。
selectionが入っていない場合はExportAll、selectionが入っていると
現在選択中のノードのみが出力されます。

Skelを出力する

デフォルトだとSkelは出力されないので、Skelを含む場合はオプションを指定します。

cmds.mayaUSDExport(file=exportPath,
                   selection=True,
                   exportSkels="auto",
                   exportSkin="auto")

引数はBoolではなくStringで、Exportの方法次第でフラグを指定します。
autoの場合は、Skel以下に自動で必要なJointを生成して出力し
explicitの場合は、指定のSkelのみ出力するようにします。

このあたりのフラグは、GUIから実行した場合と共通です。
これ以外のColorSetsやUVSetsは exportUVs=True exportColorSets=True でON/OFFすることができます。

Animationを出力する

Animationを出力する場合は、frameRangeを指定します。

cmds.mayaUSDExport(file=exportPath,
                   selection=True,
                   exportSkels="auto",
                   exportSkin="auto",
                   frameRange=[1,30],
                   frameStride=0.5
                   )

Animationは、frameRangeで指定したStartFrameとEndFrameの間を基本全フレームベイクされます。
どれぐらいサンプリングするかは frameStrideで指定することができて
上の例の場合は0.5フレームおきにサンプリングするようになります。

インスタンス出力

次は、MayaのInstanceがどうなるかテストしてみます。

cmds.mayaUSDExport(file=exportPath,
                   selection=True,
                   exportInstances=True
                   )

デフォルトONですが、オプションでInstanceを有効にするかを指定することができます。

Maya側ではこんなかんじで、1つのShapeをInstanceでDuplicateしました。

結果。

インスタンスになっている場合どうなるかというと、 MayaExportedInstanceSourcesに
実態のMeshがExportされて
配置側にはリファレンスされます。

    def Xform "pCube4" (
        instanceable = true
        prepend references = </MayaExportedInstanceSources/instance_pCube1_pCubeShape1>
    )
    {
        double3 xformOp:translate = (5.87835563344876, 0, 0)
        uniform token[] xformOpOrder = ["xformOp:translate"]
    }

リファレンスしているPrimは、instanceable = true としてリファレンスされています。

各ノードごとの指定

ここまではExport時のフラグとその挙動をみてきました。
次からは、Exportする各Mayaのノードに対して、USD用のアトリビュートの指定を
どうしたらいいかをまとめてみます。

各ノードに対しての指定は、AddAttrで USD_#### という決まった名前で
アトリビュートをつけることで指定ができます。

Kindの指定

まずは、Primに指定するKind。
そもそもKindとはなんぞ?という人は

https://fereria.github.io/reincarnation_tech/11_Pipeline/01_USD/11_kind_modelhierarchy/
こちらを参照してください。

Kindを追加したい場合は、ノードに対して USD_kind アトリビュート(string)を追加します。

追加することで、ExportされたPrimに対してKindを指定することができました。

CustomAttributeの指定

Mayaのノードに対して追加したAttributeをUSD側にも出力したいというケースは
かなり多いハズです。
昨日調べた段階だと普通にAddAttrしただけだと出力されなかったので
てっきり対応していないのか?と思いましたが
ちゃんと対応していました。

まず、ノードに対して USD_UserExportedAttributesJson というアトリビュート(string)
を追加します。
そして、そのアトリビュートにJsonでExport設定を書きます。
書き方は

{"<AttrName>": {<option>}}

です。
optionは、現状見つかったもので

"translateMayaDoubleToUsdSinglePrecision": true,
"usdAttrName": "<Name>"

この2つ。
このオプションをなしで出力した場合、

uerProperties:### という形で出力されます。
こうではなく、自分で指定したネームスペースや名前で出力したい場合は
usdAttrName に名前を指定することで、USD担ったときのアトリビュート名を
指定できます。

こんな漢字で、 usdAttrName を foo のようにすると

こうなります。

ModelHierarchyのチェック

最後にKind周りの挙動。

cmds.mayaUSDExport(file=exportPath,
                   selection=True,
                   exportInstances=True,
                   kind="component"
                   )

Exportコマンドには kind を指定することができて
この kindの指定によって、Export時にエラーを出すことができます。

Kindのルールは assembly > group > component
そしてcomponent 以下には model(modelは 上記3つを含む)は含まないという
ルールがあります。
このルールに沿っていない場合は、Export時にエラーが出せるよ... というのが
このkind指定です。

なのでまずはテストで、 kind で component を指定しておきます。

こんなかんじのノードをつくり、 null1 には assembly pSphere1に componentを
指定しておきます。

この状態で実行すると、

# Error: RuntimeError: </null1> has kind 'assembly' but the export root kind option is set to 'component'; expected that or a derived kind -- Runtime Error in _AuthorRootPrimKinds at line 152 of S:\jenkins\workspace\ecg-mayausd-full-2022-python3-windows\ecg-maya-usd\maya-usd\lib\mayaUsd\fileio\jobs\modelKindProcessor.cpp # 

ランタイムエラーになりました。
どういうことかというと、 component でExportしているのに、null1が assembly になっているので
ModelHierarchyのルールに則って考えると間違っているということになります。
この場合、 kindをkind="assembly"とするか、USD_kindの指定が意図していないゆえのエラーとして
USD_kind側を修正します。
どちらにするかは作っているルール次第ですが
Export時にKindのチェックをできて、エラーにできるというのがメリットですね。

その他検証事項

だいぶできることが増えましたが、これ以外にもっと色々仕込みたい!!という場合
chaserという昨日を利用することで、もっと色々とできるようです。

https://github.com/Autodesk/maya-usd/blob/dev/test/lib/usd/plugin/infoImportChaser.cpp

maya-usdのGithubのサンプルに infoImportCaser.cppというのがあって
これを見ると何ができるとわかるのですが、
これは

cmds.mayaUSDImport(
    file='/tmp/test.usda',
    chaser=['info'])

Import時やExport時の引数で、なにかしらの特定の処理を呼び出すことができる拡張を
自分で作れるというものです。
上の例だと、 info を指定すると、USDのCustomLayerDataに指定された値を
Mayaのノードとしてロードする際に展開してくれる...といったもののようです。

サンプルはimportですが、Export時にも呼び出せるようなので、
例えば特定のアトリビュート名の場合はJsonで指定しないでも出力
できるようにしたり(Alembicはこれをやってる)
AssetInfoやMetadataを出力するといった任意の処理もつけられるのではないかと思います。
どうやって使うかは要検証。
plugInfoで指定もできたりするようなので、このあたりを作れば
Exporterを自分用に拡張できるんじゃないかと思います。