OpenUSD(Universal Scene Description) をローカルでビルドし、usdview を単体で動かしたうえで、PySide6 のウィジェットに埋め込んでカスタムする手順をまとめました。
uv で Python 環境を用意し、StageView を使った埋め込みと、Qt UI からの操作までを一通り扱います。
USD をこれから触る人・ビルドで詰まった人向けの記録です。
この記事でわかること
- OpenUSD を uv でビルドする手順
- usdview を単体で起動する方法(uv コマンド・Python スクリプト)
- PySide6 で USD Viewer を埋め込んだウィジェットの作り方
- Qt UI ファイルでカスタムビューワー(カメラリセット・レンダーモード・HUD・BBox など)を操作する流れ
前提条件
- Python 3.11、uv が利用できること
- macOS でビルドする場合、Xcode やビルドツールの準備(公式 OpenUSD を参照)
開発環境
- macOS Sequoia 15.5
- VS Code
- zsh 5.9 (arm64-apple-darwin24.0)
サンプルリポジトリ

この記事の流れ
- Universal Scene Description (USD) とは?
- ローカルで OpenUSD をビルドする(Python / uv)
- USD Viewer を単体で起動する
- USD Viewer を PySide6 で埋め込んでカスタムする
Universal Scene Description (USD) とは?
ざっくり言うと、複雑になった 3D アセットのやり取りを、USD が中間に入って円滑にするという解釈でよいと思います。公式「USD とは」の抄訳です。
映画やゲームなどの CG パイプラインでは、大量の 3D データ(シーン記述)を生成・保存・送信する必要があります。これらはアプリごとにフォーマットが異なり、他アプリで読めないことが一般的です。
Universal Scene Description (USD) は、この課題を解決するために公開されたソフトウェアで、複数要素で構成された 3D シーンを効率的かつスケーラブルに共有・拡張するための基盤です。モデルやアニメーションの交換だけでなく、仮想セット・シーン・ショットにまとめ、破壊的でない編集や、単一 API・シーングラフによるジオメトリ・シェーディング・ライティングなどのプレビュー・編集を可能にします。オープンソースで、Apache 2.0 に近い TOST ライセンスで提供されています。
ローカルで OpenUSD をビルドする
1. リポジトリの取得
サブモジュールで追加する場合:
git submodule add https://github.com/PixarAnimationStudios/OpenUSD OpenUSDクローンする場合:
git clone https://github.com/PixarAnimationStudios/OpenUSD.git2. uv で仮想環境を作り、ビルドを実行
公式 OpenUSD のビルドドキュメント を確認しつつ、例としては次のようにします。
uv init -p 3.11
uv add PyOpenGL PySide6 numpy
uv run OpenUSD/build_scripts/build_usd.py BuildUSDビルドが成功すると、次のようなメッセージが出ます。
Success! To use USD, please ensure that you have:
The following in your PYTHONPATH environment variable:
/Users/Username/path/custom-embed-usdviewer/BuildUSD/lib/python
The following in your PATH environment variable:
/Users/Username/path/custom-embed-usdviewer/BuildUSD/bin3. 環境変数の設定
PYTHONPATH:
cat > .env <<EOL
PYTHONPATH=./BuildUSD/lib/python
EOLPATH:
export PATH=./BuildUSD/bin:$PATHUSD Viewer を単体で起動する
uv で usdview を直接起動
uv run --env-file=.env usdview OpenUSD/extras/usd/tutorials/convertingLayerFormats/Sphere.usda初回は起動に時間がかかることがあります。
Python スクリプト経由で起動
open_usd_viewer.py を次の内容で作成します。
"""Simple USD viewer using pxr.Usdviewq."""
import sys
import pxr.Usdviewq as Usdviewq
if __name__ == "__main__":
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
try:
usd_path = "assets/Sphere.usda"
sys.argv.append(usd_path)
Usdviewq.Launcher().Run()
except Usdviewq.InvalidUsdviewOption as e:
print("ERROR: " + str(e), file=sys.stderr)
sys.exit(1)起動:
uv run open_usd_viewer.pyUSD Viewer を PySide6 で埋め込んでカスタムする
usdview を埋め込んだウィジェットを作成
ポイントは from pxr.Usdviewq.stageView import StageView で StageView を使うことと、ラッパー関数を用意して後から UI(ボタン・コンボボックスなど)から操作できるようにすることです。
embed_usd_widget.py のコード(クリックで展開)
"""Embed a USD viewer in a PySide6 widget."""
import os
import sys
from datetime import datetime
from PySide6 import QtCore, QtWidgets
from pxr import Usd, UsdUtils
from pxr.Usdviewq.stageView import StageView, RenderModes
class EmbedUSDWidget(QtWidgets.QWidget):
"""Widget to embed USD stage viewer."""
def __init__(self, stage=None):
super(EmbedUSDWidget, self).__init__()
self.model = StageView.DefaultDataModel()
self.stage = stage
self.view = StageView(dataModel=self.model)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.view)
layout.setContentsMargins(0, 0, 0, 0)
if self.stage:
self.set_stage(self.stage)
self.view.updateView(resetCam=True, forceComputeBBox=True)
def image_save(self):
image = self.view.grabFramebuffer()
timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
os.makedirs("screenshots", exist_ok=True)
filename = f"screenshots/screenshot_{timestamp}.png"
image.save(filename)
def set_stage(self, stage):
self.model.stage = stage
def set_render_mode(self, mode):
if mode in RenderModes:
self.model.viewSettings.renderMode = mode
def reset_camera(self):
self.view.updateView(resetCam=True, forceComputeBBox=True)
def show_hud(self, enable=True):
"""Show the HUD (Heads-Up Display)."""
self.model.viewSettings.showHUD = enable
def show_bboxes(self, enable=True):
self.model.viewSettings.showBBoxes = enable
def closeEvent(self, event):
"""Close event handler for cleanup."""
self.view.closeRenderer()(原文の EmmbedUSDWidget → EmbedUSDWidget、Close envet → Close event、コメントの HUD 表記を統一しています。)
Qt UI でカスタムビューワーを作る
Qt Designer(Qt Creator)で .ui ファイルを作成し、そのレイアウトに上記の Embed USD ウィジェットを追加します。
UI のボタン・コンボボックス・チェックボックスを、ウィジェットの reset_camera、set_render_mode、show_hud、show_bboxes、image_save などに接続します。
- UI ファイル例: usdViewerController.ui
mkdir -p UI && curl -L -o UI/usdViewerController.ui https://raw.githubusercontent.com/testkun08080/custom-embed-usdviewer/main/UI/usdViewerController.uiapp.py では、QUiLoader で UI を読み込み、メインレイアウトに EmbedUSDWidget を追加します。
その後、各 UI 要素のシグナルをウィジェットのスロットに接続します(レンダーモード、HUD、BBox、AOV 選択など)。
詳細は custom-embed-usdviewer の app.py を参照してください。
起動:
uv run app.py
まとめ
- OpenUSD をローカルでビルドし、usdview を単体で動かしたうえで、PySide6 の StageView を使い、USD Viewer をウィジェットとして埋め込む流れを紹介しました。
- Qt の UI ファイルでボタン・コンボボックスを用意し、カメラリセット・レンダーモード・HUD・BBox 表示・スクリーンショットなどをラッパー経由で操作できるようにすると、社内のプレビューツールやビューワーとして拡張しやすいと思います。