[Omniverse] Extensionの作り方

  • by

OmniverseのExtensionを追加することで、機能を拡張していくことができます。
今回はExtensionの作り方について書いていくことにしました。

OmniverseのExtensionとは ?

Extensionは、他のDCCツールでの「プラグイン」「アドオン」のようなものと思ってもらえるとよいかと思います。


※ Omniverseではもっとたくさんの機能拡張要素があります。ここではExtensionに絞りました。

ベースに「Omniverse Kit」というコア環境があります。
これに「Extension」として機能を追加していきます。
ExtensionはPythonスクリプトで特定のルールに沿って記載します。

このKitとたくさんのExtensionをまとめることで「Omniverse App」(アプリケーション/ツール)となります。
「Omniverse Create」や「Omniverse View」も「Omniverse App」です。
用途別にOmniverse Appが存在することになります。
ベースとなる「Omniverse Kit」は、Python、USDやPhysics、RTXレンダラなどたくさんの機能が用意されてます。
大部分はPythonからアクセスすることができます(C/C++を使ってアクセスする箇所もあり)。
Kitを使って何か処理を行う機能を実現するのがExtensionの役割になります。

Omniverse CreateでのExtensionフォルダ

Omniverse Create 2022.1.3で確認しました。
Omniverse Createのインストールフォルダは、Omniverse LauncherからSettingsを表示し、「LIBRARY PATH」で確認できます。

以下のような構成になります。

[create-2022.1.3]
  [exts]  ← ここに独自Extensionを入れる
  [extscache]
  [kit]  ← Omniverse Kit
    [extensions]
    [exts]
    [extscore]
    [extsPhysics]

この中の「exts」に独自に作成したExtensionを入れます。
「kit」はOmniverse Kitです。この中にもExtensionフォルダが存在します。
ここはいじることはないかと思います。
extscache、kit/extensions、kit/exts、kit/extscore、kit/extsPhysicsにもExtensionが入っています。

Extensionの参考

GitHubにサンプルExtensionをアップしてますのでよろしければご参照くださいませ。
https://github.com/ft-lab/omniverse_sample_scripts/tree/main/Extensions

また、完成Extensionとして「SetOrigin」というのを公開してます。
https://github.com/ft-lab/Omniverse_extension_SetOrigin

以下はKitのドキュメントです。
https://docs.omniverse.nvidia.com/py/kit/index.html

ただ、Kitのドキュメントは難しいです。
このドキュメントははじめに見るものではなく、ある程度理解が進んだ後に見るのがよいかと思います。
Extensionの書き方/ルールは、このドキュメント内の「Extensions」( https://docs.omniverse.nvidia.com/py/kit/docs/guide/extensions.html )が参考になります。

Omniverseの場合、Omniverse CreateやKitについているExtensionの大部分はソースが公開されています。
これを読むのがExtensionの様々な実装を知るのに役に立つと思います。

Extensionを作るのに必要な知識

  • Pythonプログラミング
  • USDの知識

Omniverseでは、特にUSDについて知識があるのは必須事項になります。
PixarのUSDのページ( https://graphics.pixar.com/usd/release/index.html )も参考になります。

Extensionを作成

GitHubにアップしている

https://github.com/ft-lab/omniverse_sample_scripts/tree/main/Extensions/ft_lab.sample.hello

を例として説明していきます。
カスタムでExtensionを作る方法以外に、Extensionsウィンドウの
左上の「+」を押してテンプレートを作る手順もありますので、これは後述します。

以下のようにextsフォルダに「ft_lab.sample.hello」のように配置しています。

Extension名

特にルールはなさそうですが「ft_lab.sample.hello」というのは「組織名.カテゴリ.Extension名」としました。
ドットで区切る数はいくつでも問題なさそうです。

Extensionの構成

Extensionのフォルダ構成は以下のようになります。

[ft_lab.sample.hello]
  [config]
    extension.toml  ← 設定ファイル
  [data]
    icon.png   ← アイコン画像(256 x 256)
    preview.png ← Extensionの説明で表示するプレビュー
  [docs]
    CHANGELOG.md ← 変更履歴
    index.rst
    README.md   ← Extensionの説明で表示される内容
  [ft_lab]
    [sample]
      [hello]
        __init__.py
        hello.py

※ [xxx] はフォルダ

Extensionの設定は"config/extension.toml"に記載します。
"data"フォルダには、Extensionsウィンドウで表示される説明で使用する画像、
"docs"フォルダには、Extensionsウィンドウで表示される説明文など、
"ft_lab/samples/hello"でExtension名のドットごとに分割した階層としています。
この中にPythonコードを入れます。
「 *.md 」はmarkdown形式ですが、OmniverseのExtensionsウィンドウの表示はmakrdownの構文にフルに対応しているわけではありません。

config/extension.toml

"extension.toml"はExtensionの設定ファイルです。
テキストファイルで[package]や[dependencies]などのセクションごとに分かれています。

[package]
# Semantic Versionning is used: https://semver.org/
version = "0.0.1"

# Lists people or organizations that are considered the "authors" of the package.
authors = ["ft-lab"]

# The title and description fields are primarily for displaying extension info in UI
title = "Python Extension Example"
description="Very simple extension."

# Path (relative to the root) or content of readme markdown file for UI.
readme  = "docs/README.md"

# URL of the extension source repository.
repository = ""

# One of categories for UI.
category = "Example"

# Keywords for the extension
keywords = ["kit", "example"]

# Location of change log file in target (final) folder of extension, relative to the root. Can also be just a content
# of it instead of file path. More info on writing changelog: https://keepachangelog.com/en/1.0.0/
changelog="docs/CHANGELOG.md"

# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
preview_image = "data/preview.png"

# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
icon = "data/icon.png"

# We only depend on testing framework currently:
[dependencies]

# Main python module this extension provides.
[[python.module]]
name = "ft_lab.sample.hello"

以下は、[package]セクションの指定です。

"version"はExtensionのバージョン。
"authors"は制作者(複数指定可)。
"title"はExtensionの名称。
"description"はExtensionの詳細。
"category"はカテゴリ名。
"keywords"はExtensionのキーワード(複数指定可)。
"preview_image"は説明文の最後に表示される画像ファイル。
"icon"はアイコン画像ファイル。256 x 256の解像度のpngファイルとしました。

"readme"は説明文( .md )。
"changelog"は変更履歴のファイル(
.md )。

[dependencies]セクションは、このExtensionを使うにあたって必要な他のExtension(依存関係)を指定します。

例えば、以下のように書いた場合は、
このExtensionを有効にした際は"omni.syntheticdata"と"omni.audioplayer"も同時に有効になります。

[dependencies]
"omni.syntheticdata" = {}
"omni.audioplayer" = {}

[[python.module]]セクションで、対象のExtensionを指定します。

[[python.module]]
name = "ft_lab.sample.hello"

docs/README.md

Extensionsウィンドウに表示される説明文です。

# Python Extension Example [ft_lab.sample.hello]

sample extension.    

markdownの構文としては、「#」「##」「##」以外は使えないと見てよいかもしれません。

docs/CHANGELOG.md

更新履歴です。

# CHANGELOG

This document records all notable changes to ``ft_lab.sample.hello`` extension.

docs/index.rst

1行目にExtension名を指定。
それ以外は定型文、でよさそうです。

ft_lab.sample.hello
###########################

.. toctree::
   :maxdepth: 1

   README
   CHANGELOG

Pytonコードの配置

  [ft_lab]
    [sample]
      [hello]
        __init__.py
        helo.py

"ft_lab.sample.hello"の場合は、"ft_lab/sample/hello"のフォルダ構成を作ります。
ここに "__init__.py" とはじめに呼ぶコード(ここでは"hello.py")を配置しています。
入口のpyファイルさえ明示すれば、後は自由に配置できます。

__init__.py

呼び出すファイル(この場合はhello)を指定します。

from .hello import *

hello.py

import omni.ext

class HelloExtension(omni.ext.IExt):
    # ext_id is current extension id. It can be used with extension manager to query additional information, like where
    # this extension is located on filesystem.
    def on_startup(self, ext_id):
        print("[ft_lab.sample.hello] HelloExtension startup")

    def on_shutdown(self):
        print("[ft_lab.sample.hello] HelloExtension shutdown")

クラス名(ここではHelloExtension)は何でもいいです。
このクラス内の「on_startup」はExtensionを有効にしたときに呼ばれます。
「on_shutdown」はExtensionを無効にしたときに呼ばれます。

Extensionの有効化

"ft_lab.sample.hello"フォルダまるごとがExtension一式になります。
これをOmniverse Createの"exts"フォルダにコピーし、Omniverse Create上でExtensionsウィンドウを表示します。

対象Extensionを探してOnすると、このExtensionのon_startupが呼ばれます。
Offにするとon_shutdownが呼ばれます。

Extensionのテンプレートを自動生成

Extensionsウィンドウの左上の「+」ボタンから、
Extensionを格納するフォルダとテンプレートExtensionが作成できます。

「+」ボタンを押して、"New Extension Template Project"を選択。
フォルダ選択のダイアログボックスが表示されます。
次に、Extensionを格納するフォルダ名(デフォルトは"kit-exts-project")を指定します。
これは既存のOmniverse Createやextフォルダではなく、離れた場所を指定します。
ここで指定したフォルダは、新たにExtensionを検索するフォルダとして登録することになります。

Extension名はデフォルトで"omni.hello.world"となっています。

この作業を進めると、VSCodeが起動します。
extsフォルダに"omni.hello.world"が配置されています。

また、Extensionが自動で起動します。

追加されたExtensionフォルダを確認

"New Extension Template Project"の作業で新たにExtensionフォルダが追加されました。
Extensionsウィンドウの歯車のアイコンをクリックすることで、Extensionの検索パスを一覧できます。

Extensionの検索パスは、ここで新たに追加/削除できます。
ユーザExtensionとして、独自Extension格納フォルダは分けておいた方がいいかもしれません。

今回はここまでです。
Omniverse CreateとOmniverse Codeの違いも書いておいたほうがよさそうですので、これは次回テーマにする予定です。