コンテンツにスキップ

FileFormatPluginについて

Universal Scene Description AdventCalendar2021 24 日目は、FileFormatPlugin についてです。

File Format Plugin とは

https://graphics.pixar.com/usd/release/glossary.html#crate-file-format

FileFormatPlugin とは、USD の特徴的な機能の1つで
usd 以外のファイルフォーマット(FBX,OBJ,Alembic 等)を USD としてロードできるようにする機能です。

USD は、繰り返しになりますが 複数の USD ファイル(レイヤー)をコンポジションアークによって合成し
1つの Stage になります。
このときの Layer は、 usdc (バイナリ) であったり usda(アスキー) 形式のファイルですが
FileFormatPlugin を使用することで、別のファイルフォーマットであっても
あたかも USD のレイヤーを読んだかのように、別のフォーマットをロードできるようにできます。

Alembic FileFormat Plugin を使う

USD のリポジトリには、デフォルトで Alembic の FileFormatPlugin が含まれています。
https://graphics.pixar.com/usd/release/api/usdabc_page_front.html

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

USD をビルドするときに、 --alembic オプションを追加すると、AlembicFileFormat を使用できるようになります。

試しに、Blender からこんな感じの Suzanne を

Alembic で出力します。

そして、このように abc ファイルをリファレンスするレイヤーを用意します。

AlembicPlugin を使用した結果、

Alembic をリファレンスでロードすることができました。
アニメーションも持ち込みできているのがわかります。

このように、USD 以外のファイルフォーマットを 「さも USD かのように」 リファレンスにロードすることができました。

ロードした Alembic ファイルは、USD として扱うことができるので、
このように Material を Assign することができます。

Alembic を Reference したあとに、MaterialAssign ができました。

図に表すとこのようになります。
Alembic であっても、ファイルは Layer として扱われ、コンポジションされ、Stage になります。

このように FileFormatPlugin をしようすることで、異なるファイルフォーマットを
事前にコンバートすることなく、USD ファイルと同様にできるようになります。

デフォルトで使用できるのは、AlembicPlugin ですが
たとえば FbxFileFormat 等を作れば、すでにある Fbx アセットを USD として配置できるようになります。
もちろん、Alembic と Fbx、その他対応するプラグインがあれば
様々なファイルを USD に取り込みシーンを構築することが可能になります。

FileFormatPlugin を拡張すれば、USD への導入がやりやすくなるのではないかと思います。

FileFormatPlugin と DynamicFileFormat

FileFormatPlugin は、上の AlembicFileFormatPlugin のように「ある別のフォーマットを USD としてロードする」FileFormatPlugin と
もう1つ 「ある指定の拡張子にすることでプロシージャルにシーングラフを構築する」 DynamicFileFormat が存在しています。

extras/usd/examples/usdDancingCubesExample

それが、この DancingCubesExample です。
このプラグインを使用して、 DynamicFileFormat がどんなものかを見ていきます。

DancingCubeExample を試してみる

まずは、 AssetResolution(1) - usdResolverExample で USD をビルドしておきます。

そして、 USD/share/usd/examples/plugin 以下の usdDancingCubesExample と usdDancingCubesExample.dll を plugin/usd フォルダにコピーします。
コピーしたら準備完了です。

< InstallDir >/plugin/usd/usdDancingCubesExample/resources/usdDancingCubesExample/dancingCubes.usda

この DancingCubeExample プラグインを使用したサンプルは、上記のフォルダにあるので、
ンプルの usda ファイルがあるので、usdview でロードしてみます。

実行するとこのようになります。
Dancing している Cube の Stage を開くことができました。
dancingCubes.usda を開いて中を確認すると、

1
2
3
4
5
6
7
8
9
    Usd_DCE_Params = {
        int perSide = 15
        int framesPerCycle = 36
        int numFrames = 200
        double distance = 6.0
        double moveScale = 1.5
        token geomType = "Cube"
    }
    payload = @anon:dummy:cubes.usddancingcubesexample@

Payload でロードされているのは anon: つまりは 自動生成された無名レイヤの識別子で(参考)
usddancingcubesexample という拡張子のファイルは存在していませんし、 Root 以下の prim_0 ~を含むような
USD のレイヤーは存在していません。
しかし、実際には Cube が動く Stage が生成されています。

この DancingCubeExample は、Prim や Schema、Attribute がすでに USD ファイルに保存されているのではなく、
pluginfo.json で追加した Metadata (Plugin で CustomMetaData を追加する方法については こちら の情報を介して、USD のシーングラフを動的に、プロシージャルに生成しています。

動的に生成しているので、
例えば、 dancingCubes.usda の Usd_DCE_Params の perSide を 5 にしてみます。

結果、Cube の数が 5 個に変化しました。
このように、シーングラフを Plugin 内で動的に構築できるのが FileFormatPlugin です。
これを利用すれば、わざわざファイルを用意しなくても
なにかしらの情報をもとにして USD のシーングラフを生成することができます。
そしてそれをコンポジションで合成することができますので、
例えばレイアウトした各 Shot のデータを動的に生成させたりといったことも可能になります。

SdfFileFormat

最後に軽く実装について触れておきます。
FileFormatPlugin も DynamicFileFormatPlugin も、 SdfFileFormat クラスを継承することで実装します。

Info

USD/extras/usd/examples/usdObj/fileFormat.cpp

の、_ReadFromStreamを参考。
UsdObjTranslateObjToUsd クラスで obj ファイル→USDのシーングラフに変換していて、
その結果を layer->TransforContenxt(objAsUsd); で渡しています。

DynamicFileFormat も、SdfFileFormat クラスを継承して実装するのは共通ですが、

DynamicFileFormatは、Read で Stage を作り Layer を返すようにするか、あるいは
完全プロシージャルに生成するのであれば(DancingCubeExample のように)
SdfAbstractData クラスを使用することでプロシージャルに生成することが可能です。

SdfAbstractDataは、シーンディスクリプションを格納するためのインターフェースで
ある SdfPath,Field をキーにしてある値のペアを持ちます。

たとえば、上記のようなシーングラフの場合(DancingCubeExample の生成例)

SdfPath /Root/prim_0/prim_0/prim_0 の Field が TypeName なら Cube を返すし
SdfPath /Root の PrimChildren なら Root の子 Prim を返すし、
SdfPath / (RootPath) で、 Field が DefaultPrim なら DefaultPrim を返します。

このように、SdfAbstractData は ある問い合わせ(key)に対しての結果を 返すことで
動的にシーングラフを構築しています。

Info

DancingCubeExampleの場合は、

USD/extras/usd/examples/usdDancingCubesExample/data.cpp

にて、SdfAbstractData クラスが実装されています。

PcpDynamicFileFormatInterface

また、DynamicFileFormatPlugin の場合
MetaData から動的精製用のパラメータ(Usd_DCE_Params)を受け取るために
SdfFileFormat とともに、 PcpDynamicFileFormatInterface を実装します。
PcpDynamicFileFormatInterface を実装すると、アセットへの Payload がある場合
ComposeFieldsForFileFormatArguments を呼び出して、
FileFormatPlugin への引数を生成します。

Info

DancingCubeExample の場合、

USD/extras/usd/examples/usdDancingCubesExample/fileFormat.cpp

上記ファイルで ComposeFieldsForFileFormatArguments が実装されています。
この中で、MetaDataの辞書型から FileFormatArguments を生成して、 FileFormatPlugin の引数にしています。

このあたりの実装は、私自身もまだ勉強中ではあるので
別途カスタムな FormatPlugin 実装の記事を書こうと思います。

まとめ

以上が FileFormatPlugin でした。
実装についてはかなり端折りましたが、FileFormatPlugin がどんなものかわかったでしょうか。

FileFormatPlugin を使用すれば、USD 以外のファイルも USD として扱うことができるようになるので
わざわざ USD にコンバートしなくても、今までのアセットを有効活用したり、異なる FileFormat を USD で合成したり
できるようになるとわかりました。

また DynamicFileFormat Plugin を使用すれば、USD の Plugin 内で動的にシーングラフを構築できるので
ファイルをわざわざ作らなくても、決められた処理をプロシージャルに構築が可能になります。

この機能は、CompositionArc・Schema・AssetResolution といったこれまで解説してきた機能と同じく
USD のパイプラインを構築する上で強力な武器になりますので
パイプライン構築の際にはぜひとも取り入れてほしい機能です。