👏

USD FileFormatPluginを使おう

5 min read

今回はDCCツールでのUSD解説ではなく、USDの持っている便利機能の1つ「FileFormatPlugin」
について説明します。

FileFormatPluginとは?

FileFormatPluginとは、USD以外の対応したファイルフォーマット(abc,obj等)を
USDのシーングラフとしてロードできるようにできるプラグインのことです。

たとえば、

https://graphics.pixar.com/usd/docs/api/usdabc_page_front.html
UsdAbc プラグインは、Alembic File Format Pluginで、
このプラグインを使用すると、AlembicのモデルをUSDで開けるようになります。

ビルドする

まずはUSDをビルドします。
UsdAbcはデフォルトではOFFになっているので、ビルドするときに引数でビルドするように指定をします。

ビルドは、 VS 2017 + Python37 環境で実行します。
Pythonはあらかじめ使用するPythonのバージョンを環境変数に入れておきます。
3系を入れておけば、ビルドもPython3環境になります。

そしたら、開発者コマンド コマンドプロンプトを開き、

python build_scripts\build_usd.py --alembic --materialx C:\USD

ビルドスクリプトを実行します。
Alembicと、ついでにMaterialXのプラグインもビルドしておきます。

以上で準備完了です。

開く

ビルドが完了したら、usdview でabcファイルを開いてみます。

usdview D:\suzanne.abc

ファイルを開くときは、このようにあらかじめUSDに変換等はせず
abcファイルをそのまま指定します。

結果。
Windowのタイトルバーを見ると、ファイルパスは D:/suzanne.abc となっていて
開いているのがUSDではなく、abcファイルだというのがわかります。

コンポジション

FileFormatPluginを使用すれば、別のフォーマットもUSDを開くように
対応するファイルフォーマットを開くことができました。

しかし、FileFormatPluginの面白いところは
指定のフォーマットを「USDのレイヤーと同じように」扱う事ができる点です。

なので、ただ開くだけではなく
abcファイルをコンポジションでロードすることもできます。

sample.usda
#usda 1.0

def "sampleUSD"(
    prepend references = @suzanne.abc@
)
{
}

まず、このようなレイヤーを用意します。
そしてあるPrimに対してAlembicをリファレンスでロードします。

無事abcファイルをリファレンスで読み込むことができました。

#usda 1.0

def "sampleUSD"(
    prepend references = @suzanne.abc@
)
{
    rel material:binding = </Model/Material/MyMat>
}

def "Model"
{
    def "Material"
    {
        def Material "MyMat"
        {
            token outputs:surface.connect = </Model/Material/MyMat/testShader.outputs:surface>

            def Shader "testShader"
            {
                uniform token info:id = "UsdPreviewSurface"
                color3f inputs:diffuseColor = (1,0,0)
                float inputs:metalic = 0.9
                float inputs:roughness = 0.2
                float inputs:test = 1
                token outputs:surface
            }
        }
    }
}

ロードされたファイルは、USDのシーングラフとしてロードされているので
当然読み込んだメッシュに対してマテリアルをアサインする...といったことも可能です。

そして、リファレンスで読み込んでいるので
元の abc ファイルが更新されれば sample.usda を開きなおすとモデルもアップデートできます。

MaterialX

Alembicと同様に、MaterialXもFileFormatPluginでUSDにロードできるようになっています。

https://graphics.pixar.com/usd/docs/api/usd_mtlx_page_front.html
ConceptMappings というのをみるとわかる通り、
プラグイン(UsdMtlx)を使用すると、
MaterialXのネットワークを、USDのシェーディングネットワークに展開します。

MaterialXのExamplesに UsdPreviewSurface というサンプルがあるので、
これを usdview で開いてみます。

mtlx ファイルを開くことができました。

usdで保存

FileFormatPluginを使用すれば、usdaへの変換もすることができます。

usdcat D:\suzanne.abc > sample.usda

usdcat を利用して、指定のAlembicファイルをusdaに変換する例です。
これを利用すれば、指定のAlembicを全部まとめてバッチで変換...のようなことも可能になります。

実装したい場合のサンプル

公式で用意されている Alembic と MaterialX を紹介しましたが
このFileFormatPluginは、自分でも簡単に実装することができます。
そのサンプルが、
USDリポジトリの extras/usd/examples 以下にある usdObj です。
これは、objファイルのFileFormatPluginになります。

今回は詳細な実装方法は省きますが、
ポイントは2つで、

{
    "Plugins": [
        {
            "Info": {
                "Types": {
                    "UsdObjFileFormat": {
                        "bases": [
                            "SdfFileFormat"
                        ],
                        "displayName": "USD Tutorial Rudimentary OBJ",
                        "extensions": [
                            "obj"
                        ],
                        "formatId": "obj",
                        "primary": true,
                        "target": "usd"
                    }
                }
            },
            "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@",
            "Name": "usdObj",
            "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@",
            "Root": "@PLUG_INFO_ROOT@",
            "Type": "library"
        }
    ]
}

1つめは、 plugInfo.json で
どの拡張子の時にどのPluginを使用するか指定する部分。
この場合なら extensions で obj が指定され、
Types の UsdObjFileFormat で、呼び出すクラスを指定しています。

2つ目がプラグインの本体になるクラスの実装で、
サンプルの場合は fileFormat.cpp がそれにあたりますが
SdfFileFormat を継承したクラスを用意して
必要な関数を実装します。

ファイルをロードしたときに実行されるのが Read関数で
フォーマットをトラバースして、USDのシーングラフを組み立てた結果を
layer にセットします。

サンプルでは、

SdfLayerRefPtr objAsUsd = UsdObjTranslateObjToUsd(objStream);

このように、objファイルを変換する関数が translator.cpp に用意されていて
この中で obj をパースして、USDのシーングラフとして再構築をしています。

layer->TransferContent(objAsUsd);

そしてその変換結果を、 TransferContent でセットしています。

このあたりの実装方法は、別途Techページ側にまとめようかと思います。

まとめ

以上がFileFormatPluginについての解説でした。
この機能を使用して、Pluginを実装したり Alembic や MaterialX 等のPluginを使用すれば
既存のアセットを生かした形で、USDのパイプラインの構築が可能になったりして
選択肢の幅が広がります。
こうした機能で、より良いパイプラインを作っていけたら良いなぁと思います。

GitHubで編集を提案

Discussion

ログインするとコメントできます