0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Omniverse Kit App Templateを使ったアプリ開発の流れ - Extensionの開発とサンプルプログラム実装 -

Posted at

前回の記事ではOmniverseでのKit App Templateを使ったアプリの構築・ビルド・起動までの流れをご紹介しました。

今回はExtensionを作りオリジナルの機能を作ってみましょう。
前回と同様、またkit-app-templateの下でrepo.bat template newを実行します。

repo.bat template new

ナビゲーションで、今後はExtensionを選びます。

  • Extension Templateを選びます。今回はPythonを使ったサンプル実装を行うため、Basic Python Extensionを選択します。
  • Extensionの名前を入力します。
  • Extensionの表示名を入力します。
  • バージョンを入力します。

Extensionを作ることができました!

スクリーンショット 2025-01-02 8.56.59.png

エクスプローラー上で新しいExtensionの関連ファイルが
作成されていることを確認できます。

スクリーンショット 2025-01-02 8.57.19.png

次にExtensionのサブディレクトリの中にあるExtension.pyを開きます。
この中にはpython言語でデフォルトのExtension用のコードが記述されています。

スクリーンショット 2025-01-02 8.57.49.png

この中で新しいExtesion用のコードを実装していきましょう。

ここでは独自ウィンドウで
Hello Omniverse!と表示するExtensionを作ります。

UIのサンプルコードを参考にして、python プログラムを実装してください。
on_startup関数はアプリが作成され、Extensionを作成しtらちじゅ

import omni.ui as ui
def on_startup(self, _ext_id):
    """This is called every time the extension is activated."""
    print("[my_company.my_python_extension] Extension startup")

    self._window = ui.Window("My hoge", width=300, height=200 )
        with self._window.frame:
            with ui.VStack():
                ui.Label("Hello, Omniverse!")
def on_shutdown(self, _ext_id):
    if self._window:
        self._window.destroy()
        self._window = None

書き終えたら、.kitファイルにこのExtension
の依存関係について追記します。

スクリーンショット 2025-01-02 9.11.50.png

"my_company.my_python_extension" = {}

書き終わったら、repo.bat buildを実行します。

repo.bat build

ビルドが終わったらアプリケーションを起動します。

repo.bat launch

Applicationで確認してみましょう。
先ほど実装したウィンドウとテキストが
表示されていることが確認できます。

スクリーンショット 2025-01-02 9.57.49.png

さらにステップアップし、StageにあるUSDの操作をするようなサンプルプログラムを作ってみましょう。

import omni.ui as ui
import omni.ext
import omni.usd
import omni.kit.commands
import carb
from pxr import Usd, UsdGeom, Sdf, Gf


# Functions and vars are available to other extensions as usual in python:
# `my_company.my_python_extension.some_public_function(x)`
def some_public_function(x: int):
    """This is a public function that can be called from other extensions."""
    print(f"[my_company.my_python_extension] some_public_function was called with {x}")
    return x**x


# Any class derived from `omni.ext.IExt` in the top level module (defined in
# `python.modules` of `extension.toml`) will be instantiated when the extension
# gets enabled, and `on_startup(ext_id)` will be called. Later when the
# extension gets disabled on_shutdown() is called.
class MyExtension(omni.ext.IExt):
    """This is a blank extension template."""
    # ext_id is the current extension id. It can be used with the extension
    # manager to query additional information, like where this extension is
    # located on the filesystem.
    def on_startup(self, _ext_id):
        """This is called every time the extension is activated."""
        print("[my_company.my_python_extension] Extension startup")


        self._window = ui.Window("Local Object Mover", width=300, height=100)
        with self._window.frame:
            with ui.VStack():
                self._button = ui.Button("Move Object", clicked_fn=self.on_button_click)

        self._usd_context = omni.usd.get_context()


    def on_button_click(self):
        self._stage = omni.usd.get_context().get_stage()
        # Get default prim.
        defaultPrim = self._stage.GetDefaultPrim()
        # Default prim path.
        defaultPrimPath = defaultPrim.GetPath().pathString
        print("DefaultPrim : " + defaultPrimPath)

        # Cone path.
        orgPath = "/World/Cone"
        cone_prim = self._stage.GetPrimAtPath(orgPath)
        translate_attr = cone_prim.GetAttribute("xformOp:translate")

        if not translate_attr:
            translate_attr = cone_prim.CreateAttribute("xformOp:translate", Sdf.ValueTypeNames.Float3)
            translate_attr.Set(Gf.Vec3f(0.0, 0.0, 0.0))

        current_translate = translate_attr.Get()
        # Move the cube by 10 units on the X axis
        new_translate = Gf.Vec3f(current_translate[0] + 10.0, current_translate[1], current_translate[2])

        translate_attr.Set(new_translate)
        print(f"Moved cube to: {new_translate}")

    def on_shutdown(self):
        """This is called every time the extension is deactivated. It is used
        to clean up the extension state."""
        print("[my_company.my_python_extension] Extension shutdown")
        if self._window:
            self._window.destroy()
            self._window = None

importの内容

omni.ui

Omniverse Kit におけるUI(ユーザーインターフェイス)構築用のモジュールです。Window や Button など、基本的なUIパーツを提供します。

omni.ext

Omniverseの拡張機能を作る際に必要なインターフェイスを提供するモジュールです。拡張は omni.ext.IExt を継承して実装します。

omni.usd

USD のステージ(シーンデータ)を扱うための Omniverse 固有のヘルパーモジュールです。get_context() を使うことでステージへのアクセスが簡単に行えます。

omni.kit.commands

Omniverse Kit 内で提供される各種コマンドを使うためのモジュールです。UI 操作などからコマンドを実行して履歴管理・アンドゥ/リドゥを行う場合などに利用します。
###carb
NVIDIA の低レベルライブラリ群(カーボン)のモジュールです。ログ出力やプラグイン管理など、Omniverse Kit の内部機能と連携する際に使用します。

pxr のモジュール (Usd, UsdGeom, Sdf, Gf)

Pixar が開発した USD (Universal Scene Description) を扱うための低レベルAPIです。シーン内の各種プリム(オブジェクト)や、Sdf で定義されるパス、Gf の線形代数機能(ベクトルや行列など)を使用します。

USDの位置更新のための実装

今回はボタンを押した時に、Stageの中にあるUSDを動かすためのコールバック関数をon_shutdown(self)で実装しています。その中の処理について解説していきます。

USD ステージの取得

omni.usd.get_context().get_stage() で、現在のステージ(シーン)の参照を取得します。

Default Prim の確認

defaultPrim = self._stage.GetDefaultPrim() でステージ内のデフォルトプリムを取得し、パスをコンソールに出力しています。ここでは動作確認程度で実際の処理には使っていません。

Cone Prim の取得

今回は先ほどのようなConeオブジェクトを動かすサンプルとします。
orgPath = "/World/Cone" として、シーン内の /World/Cone にあるプリム(円錐)を取得します。これを cone_prim として扱い、移動属性(xformOp:translate)を操作しています。

xformOp:translate 属性

USD のトランスフォームは通常 xformOp:translate や xformOp:rotateXYZ、xformOp:scale といった形でプリムに設定されます。ここでは GetAttribute("xformOp:translate") で既に存在しているかを確認し、なければ CreateAttribute() で新たに作成しています。Sdf.ValueTypeNames.Float3 を使うことで、「ベクトル型の属性である」という定義を行っています。

Gf.Vec3f

Pixar USD のライブラリである Gf(geometry foundation)のベクトル型です。Set() でこのベクトルを使って実際のトランスフォーム値を更新します。

位置の更新

current_translate で現在の位置を取得し、X 軸方向(配列インデックス [0])に 10.0 加算して新しい位置ベクトルを作成しています。これにより /World/Cone プリムが X 軸方向に 10 ユニット移動します。

スクリーンショット 2025-01-02 18.12.13.png

なお上記の内容までは下記のYouTubeでご紹介しています。Omniverse kit app templateを使ったアプリ開発の流れについての基本的なチュートリアルを紹介してますので、ぜひご確認ください!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?