[Omniverse] OmniGraphでPrimのAttributeを使ってパラメータを共有

前回説明したVariableは、同一OmniGraph上でのみ使用できます。
一方、USDの1つのステージ上で複数のOmniGraphを持たせてそれぞれでデータを共有したいことがあります。
後々解説する、パーティクルの発生をOmniGraphで制御する場合に
ステージを管理するAction Graphとパーティクル(実質Push Graph)の両方のグラフで同一の値を渡しあう必要が出てきます。

OmniGraphではPrimのAttributeに値を書き込み、または読み込みができます。
この仕組みを使用して複数のOmniGraph間でデータを渡しあうことが可能になります。

ここではUSD Composer 2023.2.3を使用しました。

特定のPrimにカスタム属性を追加

USD ComposerのUI上で特定のPrimに対してカスタム属性を追加することができます。
データを持つだけの存在のため、"Scope"を使用しました。
Scopeは3D空間上の位置や回転、スケールなどのTransformを持ちません。

ScopeをStageウィンドウで選択し、
Propertyウィンドウで「+Add」をクリックしドロップダウンメニューからAttributeを選択します。

Add Attributeウィンドウが表示されます。

パラメータ名 説明
Name 属性名
Type 属性の種類(Bool, Color3d, Double, Float, Int, String, Float3, など)
Custom カスタム属性にする場合はチェック
Variability Varying、Uniformのいずれか

変数として使う場合は、CustomはOn、VariabilityはVaryingのままで問題なさそうです。

Variabilityについては以下の解説を参照。
https://openusd.org/release/glossary.html#usdglossary-variability
時間経過で変化する値がVarying、固定の値がUniform、となるでしょうか。

ここではNameに"counter"、Typeに"Int"を指定しました。

PropertyウィンドウのRaw USD Propertiesを見ると、counterが追加されているのを確認できました。

Action Graphの作成とConstant Intノードを配置

Action Graphを作成し、まずint型の数値を作成します。
Constant Intノードをグラフに追加し、Propertyウィンドウより値を1234としました。

"/World/Scope"をグラフにWriteノードとして配置

この値をさきほど作成した"/World/Scope"のPrimの属性として渡します。
Stageウィンドウの"/World/Scope"をグラフにドラッグ&ドロップし、Write Attributeを選択します。

これで、Write Prim Attributeノードがグラフに追加されました。

グラフ上のWrite Prim Attributeノードを選択し、PropertyウィンドウでAttribute Nameから"counter"を指定します。
これは、"/World/Scope"のPrim内のカスタム属性です。

Constant IntノードのValue(Out)をWrite Prim AttributeノードのValue(In)につなぎます。

これで「Write Prim AttributeノードのValue」が1234と更新されました。
まだこの段階では、"/World/Scope"のPrim内のカスタム属性は更新されていないことに注意してください。

On TickでWrite Prim Attributeノードにシグナルを送る

EventのOn Tickノードをグラフに配置し、TickをWrite Prim AttributeノードのExec Inにつなぎます。

Playして"/World/Scope"のcounterの更新を確認

Playすると、"/World/Scope"のcounterが更新されているのを確認できます。

これで、指定のPrimのカスタム属性の書き込み(Write)を行うことができるようになりました。

別のOmniGraphからPrimのカスタム属性を取得

別のAction Graphを作成し、ここで更新を行った"/World/Scope"のcounterの値を取得。
スクリーンにその値を表示してみます。
ActionGraph2という名前で作成しました。

Stageウィンドウの"/World/Scope"をグラフにドロップし、Read Attributeを選択。

これでRead Prim Attributeノードが配置されました。
Read Prim Attributeノードを選択し、PropertyウィンドウでAttribute Nameより"counter"を選択します。

これで、Value(out)にcounterのint値が入ります。

この値をDraw Screen Space Textノードを使ってスクリーン上に表示します。
表示用に、To Stringノードを使ってint値をstringに変換します。

更新のシグナルを送るためにOn Tickノードを配置し、Draw Screen Space TextノードのInとつなぎます。
また、To Stringノードのout値をDraw Screen Space TextノードのTextにつなぎます。

Draw Screen Space TextノードのPositionを5,10、sizeを20に変更しました。

これでPlayすると、ビューポートの左上に1234と表示されました。

この数値は1つめのAction GraphのConstant Intの値が参照されています。
Play中にこのConstant Intの値を変更すると、リアルタイムにビューポートの左上の数値が変化することを確認してみてください。

これでAction Graph(OmniGraph)間の値の受け渡しができるようになりました。
この作法を踏まえた上で、次回は「[Omniverse] パーティクルを使う」で作成したパーティクルを任意の位置に追従するようにしていきます。

なお、物理運動として衝突が発生した際に衝突位置でパーティクルの土煙を発生させることが最終目標になります。
PhysicsもOmniGraphで検出可能です。
そのために、パーティクル用のOmniGraph(Push Graph相当)と、後で説明しますが物理運動の衝突を検出するOmniGraph(Action Graph)で連携する必要が出てきます。
ということで、今回はここまでです。