[Omniverse] metersPerUnit : USDのシーン(Stage)の単位

  • by

OmniverseにUSDをインポートする場合、もしくは直接USDを開く場合、シーン(USDの場合はStage)の単位に気を付ける必要があります。

[Omniverse] DCCツールからusd以外の3Dモデルをインポート」もご参照くださいませ。

metersPerUnit : USDのシーン単位

USDのシーンはデフォルトでcm(センチメートル)の単位を使用します。
これは、USDファイルの"metersPerUnit"で0.01が指定された状態です。
この指定がない場合は、自動的にmetersPerUnit=0.01となります。
たとえば形状の位置やメッシュの頂点座標など、位置や距離の数値の単位はcmになります。

usdaファイルではヘッダ部に以下のように記載します。

#usda 1.0
(
  metersPerUnit = 0.01
  upAxis = "Y"
)

Omniverse CreateでのmetersPerUnitの確認

ここでは、Omniverse Create 2022.3.1で確認しました。

USDを開いたとき、Layerウィンドウの"Root Layer"を選択。
Propertyウィンドウの"Meters Per Unit"で0.01(この場合はcm)を確認できます。

もし、この値が1.0の場合はシーン単位はメートル(m)になります。

metersPerUnitの値 単位
0.001 mm
0.01 (デフォルト) cm
1.0 m

これにより引き起こされる問題

では、これにより引き起こされる問題を確認していきます。
1m^2の正方形のPlaneを配置し、その上にフォトグラメトリした丸太の形状をインポートしました。
しかし、サイズが小さすぎます。

このときの丸太のusdファイルを開いてmetersPerUnitを確認します。

これを見ると1.0が入っており、これはメートル単位ということになります。
試しに、metersPerUnit=1.0のStageにPlaneを配置します。

Planeの大きさは1m^2のため、この場合は正しい寸法です。

  • ReferenceとしてUSDが参照される場合 (USDインポート時)
  • LayerとしてUSDが参照される場合

この場合に、metersPerUnitが異なってもその単位変換がされないということになります。
これはOmniverseではなく、USDの挙動になります(そのため、USD SDK側の対応が必要)。

これくらいならOmniverse側で自動で単位変換できるのでは?と思うかもしれませんが、そう簡単ではありません。
ReferenceのさらにReferenceで参照された構造の場合は?Referenceの先で複数のレイヤを持つ構造の場合は?
など、ネスト構造することにより複雑化していく問題が見えてくるかと思います。
どこかでコンバートが必要ですし、その都度の変換を行うとレスポンスに影響しそうですね。

なので、極論を言うと「USDを保存する場合は、metersPerUnit=0.01(cm)になるように強制」するのが無難と言えば無難です。

USDファイルのmetersPerUnitを0.01にするスクリプト

以下にmetersPerUnitを0.01にするサンプルスクリプトを置いています。
https://github.com/ft-lab/omniverse_sample_scripts/tree/main/Samples/UnitsToCentimeters

なお、このスクリプトを実行する際にルートのXformがdefaultPrimである必要があります。

metersPerUnitが1.0(m単位)の場合、
defaultPrimのTransformのScaleを100倍し、metersPerUnitを0.01に置き換えています。
これを行った後、USDファイルを再度保存してご利用くださいませ。

個々のUSDファイルのmetersPerUnitが0.01になるように統一しておけば、これによる形状が小さすぎたり大きすぎたりする問題は回避できます。
理想を言うと、すべてのUSDエクスポータでmetersPerUnitが0.01になるように出力してほしいところではあります。

metersPerUnitが0.01ではない実例

では、metersPerUnitが0.01ではない実例を確認していきましょう。

Omniverse Createでglbファイルをそのままインポート

Omniverse Createでglbファイルをそのまま現在のStageにインポートします。
glbはglTFファイルです。glTFのフォーマットは、シーン単位はメートルです。

以下の画像の場合、原点位置にあるリンゴが本来のリンゴのサイズになります。

ところが、glbをインポートした場合は小さすぎる(1/100倍になっている)状態です。

Omniverseに形状をインポートする場合は"Convert to USD"を使ってUSDに変換後、USDファイルをインポートするようにします。

この処理で、glTFの場合はmetersPerUnitが0.01に変換されます。

Omniverseでは、usd以外のファイルフォーマットをそのまま利用はできますが、これはキャッシュを作りそれを参照します。
操作によってはキャッシュの整合性が失われることもあり、他フォーマットを参照するのはお勧めできません。
USDに変換してOmniverseで扱うほうが安全になります。

フォトグラメトリで出力したusdzを扱う

ここではTrnio Plus( https://www.trnio.com/ )を使いました。
TrnioはiPhoneやiPadでフォトグラメトリを行うアプリです。
usdzやobj形式でエクスポートできます。

このとき、usdzをOmniverseにインポートするとします。
metersPerUnitは1.0となっているため、そのままでは小さすぎます。
ちなみに、これはTrnioのUSDエクスポートが間違っているというわけではありません。
シーン単位をcmにしないと、USDの参照構造で整合性が取れないというのが根本の原因になります。

この変換のため、usdzファイルを複製して拡張子をzipに変更。
zipを解凍し、usdcファイルをOmniverseで開きます。
上記で説明したスクリプトでmetersPerUnitを0.01に変換し、usdファイルを保存。
このusdファイルをOmniverseでインポートして使用します。

Stageの単位については以上になります。
今のところ、OmniverseでUSDを扱う場合はセンチメートル(metersPerUnit=0.01)に統一したほうがよいかも、という内容でした。