CodeLess Schemas について
USD AdventCalendar2022 19 日目は、CodeLessSchemas についてです。
CodeLessSchemas とは、通常のスキーマとは違い、その名の通り
コードを生成せずにランタイムスキーマに登録が必要な generatedSchema.usda と
plugInfo.json だけを使用して登録可能なスキーマのこと
です。
自分の記憶だとこんな機能あったっけ?という感じですが
たまたま Houdini の Karma の RenderSettings のアスキーファイルを眺めているときに
Python でコード書くときに、apiSchemas が指定されてるからこのあたりを使えばいいのか?
と思って Python の API で UsdKarma がないかを探す
が、UsdKarma は見つからない。
どうやってこのスキーマ定義してるん…?というのがきっかけです。
Houdini の usd_plugin はインストールフォルダの houdini/dso/usd_plugins にあり、
この中に usdKarma は存在しています。
のでプラグインではあります。
中にあるのは generatedSchema.usda と plugInfo.json のみ。
あれ?
で、調べていくと Codess Schemas の存在をしりました。
知らなかった。
存在を知ってしまったからにはちゃんと調べていきましょう。
Schema と CodelessSchema の違い¶
Schema とは Schemaについて ここに書かれている通り
ある UsdObject(UsdPrim)に対して共通の機能・特性を指定するものです。
USD は、Prim と呼ばれる Maya でいうところのノードのような「入れ物」が用意されていますが
通常だと、この入れ物が「どのようなものを入れられるか」は指定されていません。
この「何を入れるか」を定義するものが Schema です。
たとえば、3DCG で一般的に使われるデータ形式である Camera や Xform (Transform)
Mesh といった Schema が USD では用意されています。
この各 Schema は、データの構造(いわゆるクラス変数)と、
この Schema を操作するためのメソッドによって構成されています。
Cube を作成する UsdGeomCube であれば、Cube の大きさを定義する size 変数と
この size に値をセットしたり取得したりする GetSizeAttr 関数や
CreateSizeAttr 関数 といったものが用意されています。
このような Schema は オリジナルの New Schema Classを作る こちらの記事のように
カスタムスキーマを生成するための schema.usda に、スキーマ定義のアトリビュートを
定義し、
usdGenScehma コマンドを使用して schema.usda から cpp とヘッダファイルを生成します。
そこから、必要なファイル(Python 用のファイル等)を用意し、cmake を書いて、ビルドして
dll を生成することで Schema の登録ができます。
見てわかる通り、結構更新が手間で
変数のみで関数の実装が不要なもの、いわゆる C の構造体を定義するようなパターンだと
ここまでする必要はありません。
このように、スキーマを使用したり更新するための再コンパイルが不要で
「動的な性質」が、この CodelessSchemas の重要なコンセプトです。
手軽であることと引き換えに、CodelessSchemas は「コードを生成しない」ので
1 |
|
このような API は使用できず、一般的な USD の API を使用して
1 2 |
|
このようにして TypeName をセットしたりして Schema を定義する必要があるのに
注意が必要です。
定義してみる¶
まずは定義を作ります。
任意のフォルダ下に名前/resources/名前のフォルダを作り、その中に scehma.usda を
作ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
schema.usda はこのようにします。
基本構造は オリジナルの New Schema Classを作る この時の中身と同じですが
GLOBAL に bool skipCodeGeneration = 1 を追加しています。
1 |
|
コマンドプロンプトで schema.usda があるフォルダに移動して、 usdGenSchema を実行します。
これで無事必要なファイルが生成できました。
plugInfo.json¶
generatedSchema.usda ができたら、plugInfo.json をつくります。
plugInfo.json は、USD のプラグインを定義するためのファイルで、今回のスキーマも
どのような名前で、どのフォルダにファイルがあるのかなどを、この json で定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
サンプルからコピーして、UsdSchemaBase などを作成するプラグイン名に変更します。
CMakeLists.txt を作る¶
プラグインに必要なファイル「generatedSchema.usda」と「plugInfo.json」ができたら
この 2 つのファイルを USD のプラグインフォルダにリリースします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
plugInfo.json の @~@となっていた部分は、Cmake側で定義し、 configure_file を使用して置換します。
そしてリリース先は、 pluginNanme/resources 下に usda と json がコピーされるように指定します。
1 2 3 4 5 |
|
あとは cmake を実行すれば完了です。
テストする¶
1 2 3 |
|
準備ができたら、このような usda ファイルを作り usdview で開きます。
無事 CodelssSchemas プラグインがロードされ、 SimplePrim Schema が適応されて
intAttr と target のプロパティが定義されました。
ほかの代用方法¶
最初に説明した通り、通常の Schema とは違い codelessSchemas はコンパイルを実行しない
代わりに動的に、構造体的なスキーマ定義が可能です。
この方法に似た手段として、
PXR_DEFAULT_SEARCH_PATH を通して、その下に Class 定義の usda を用意したうえで
subLayer + Inherits で、用意したクラス定義を継承する方法が可能です。
こうすると、PrimType は使用せずクラス継承によって構造体を定義が可能です。
このほうが、CodelessSchema より簡単で、PrimType を別の用途できるというメリット
があります。
CodelessSchemas の場合は、多少の手間はできるものの
Custom Attribute の定義を使用することで、ベースの構造とそれ以外のものとを
明確に区別したり
コンポジション(Inherits)を使用しなくても、attribute のフォールバックを
使用できるというメリットがあります。
メリット・デメリットがそれぞれあるので
ケースバイケースで使うのが良いのではないかと思います。