Omniverseに3Dモデルを渡す場合、usdファイルやコネクタを経由する以外の手段も使えます。
今回は、DCCツール側でfbxファイルをエクスポートし、これをOmniverse Createに持って行く流れの覚書になります。
Omniverse Create 2021.3.3で確認しました。
Omniverseでインポートできるファイル形式
Omniverseにインポートできるファイル形式は、usd(usda/usdc)またはusdzになります。
以下のファイルフォーマットはOmniverse上でUSD形式に変換してからインポートすることができるのを確認しました。
- glTF(glb)
- obj
- fbx
上記のうち、座標位置などの数値について厳密な単位情報(m/mmなど)を持っているのは「glTF(glb)」または「fbx」ファイルのみです。
objは単位情報を持ちません。
glTFフォーマットは、メートル(m)で統一されています。
対してUSDフォーマットは、デフォルトではセンチメートル(cm)を採用しています(単位変換のオプションはUSD内部で持つことも可能)。
fbxは固定の単位を持つわけではありませんが、内部で単位を切り替えることができます。
この「単位」は、ファイルフォーマットが持つ単位である点に注意してください。
Omniverseに渡す際にその単位をUSDのcmに合わせるのは、Omniverse側の仕事になります。
usd以外のファイルのインポート方法
Contentウィンドウを表示し、対象のファイル(glTF/obj/fbx)を探します。
usd形式の場合はusdファイルをそのままシーンにドラッグ&ドロップすると、3Dモデルとして配置されます。
それ以外のファイルフォーマットの場合は、右クリックしてポップアップメニューを表示。
「Convert to USD」を選択します。
Import Optionsダイアログボックスが表示されます。
「Use meter as world unit (cm by default)」チェックボックスが単位変換っぽいですが、
これをOn/Offしても違いが分かりませんでした。
「Import」ボタンを押すと、対象のファイルと同じファイル名のフォルダが生成され、その中にコンバートされたusdが格納されます。
コンバートされたusdファイルをシーンにドラッグ&ドロップすると、3Dモデルとして配置されます。
なお、マテリアルのパラメータやテクスチャは渡されるものと渡されないものがあります。
Meshに対するマテリアル名の対応は確実に渡せるようでした。
オリジナルの3Dモデルファイルがusd以外の場合は、マテリアルパラメータはうまく読み込まれないことが多いように感じます。
基本的には、マテリアルはOmniverse上で改めて割り当てるとしたほうがよさそうです。
なお、マテリアル情報を持つ場合は、OmniPBRとして割り当てられていました。
usd以外のファイルの場合の形状サイズについて
obj/glTF/fbxをusd変換した形状をインポートするとき、いずれの場合もサイズの再調整を考慮する必要があります。
既存のシーンにドラッグでインポートしたとき、形状は参照の形になっています。
対象形状を選択し、PropertyウィンドウのTransformのScaleで倍率を変更します。
obj
Convert To USDでUSDに変換した後、
obj内の数値をmm(ミリメートル)と見た場合は、0.1倍する必要あり。
obj内の数値をm(メートル)と見た場合は、100倍する必要あり。
obj内の数値をcm(センチメートル)と見た場合は、倍率変更の必要なし。
glTF(glb)
Convert To USDでUSDに変換した後、100倍する必要あり。
fbx
Convert To USDでUSDに変換した後、一部のDCCツールからのfbx(内部的にmmで単位を持たせた場合)は0.1倍する必要あり。
単位変換については、複雑なため思考中とのことでした。
USDとその他の調整が必要なようです。
以下、フォーラムより。
https://forums.developer.nvidia.com/t/unitscalefactor-is-not-referenced-during-fbx-import/187937
Omniverseの単位や寸法について
OmniverseはUSDをベースにしているため、USDでのデフォルト単位であるcmで統一されています。
デフォルトのグリッドのサイズは100cm x 100cm(1m x 1m)です。
グリッドサイズについては、Viewport Settingsより確認できます。
PropertyウィンドウでのPositionなどの座標値は、cm単位です。
Omniverse CreateのUSDの根本の単位について
Omniverse Create 2021.3.5で確認。
2021/09/23追記。
usdでは"metersPerUnit"によりシーン単位が決定されます。
デフォルトは0.01になります。
これは、対象のusdファイルの座標値がcm単位で格納されていることになります。
1.0だとすると、usdファイルの座標値はm単位となります。
ただし、現段階のOmniverse Createでは"metersPerUnit"の対応が行われていないようです。
https://forums.developer.nvidia.com/t/3ds-max-groups-break-objects/180894/4
Pythonスクリプトの以下でこの値を確認できます。
from pxr import Usd, UsdGeom, UsdPhysics, UsdShade, Sdf, Gf, Tf
stage = omni.usd.get_context().get_stage()
# Get metersPerUnit (default : 0.01).
metersPerUnit = UsdGeom.GetStageMetersPerUnit(stage)
print(metersPerUnit)
objやfbxからConvert To USDした場合、座標値については変更されず、"metersPerUnit"の値がそれぞれのフォーマットのシーン単位によって変更が加えられるようです。
そのため、上記のTransformのScaleを変えてスケールを調整するというのはあくまで回避策で、
将来的にOmniverse Createが"metersPerUnit"の対応を行うと逆に問題になる可能性があるかもしれません。
もし、scaleを変更して整合性をcmに合わせた場合は、
以下のように"metersPerUnit"を0.01に変更する、などの調整を行った方が安全かもしれません。
from pxr import Usd, UsdGeom, UsdPhysics, UsdShade, Sdf, Gf, Tf
stage = omni.usd.get_context().get_stage()
# Set metersPerUnit.
UsdGeom.SetStageMetersPerUnit(stage, 0.01)
fbxインポート時の注意点
fbxインポート(USDにコンバート)する場合は以下を注意する必要があるようでした。
- 寸法はfbxの内部単位の指定により正しくコンバートされない場合があるため、適宜Scaleを変更する必要がある。
- ASCII文字列以外の形状名、マテリアル名、パス名、テクスチャファイル名を指定するとうまくいかない(これはUSDフォーマットの仕様)。
形状名「メッシュ1」などはNG、「Mesh1」のように指定します。 - 形状名、マテリアル名などの先頭をアルファベットやアンダーバーなどの一部の文字以外の数値を指定すると、うまくいかない(これはUSDフォーマットの仕様)。
形状名「3d_mesh」などはNG、「_3d_mesh」のように指定します。 - 1Meshに対して1Materialを割り当てること。
- USD上でのパス("/root/shape1/mesh1"などの絶対指定)で同一パスになるものは存在できません(これはUSDフォーマットの仕様)。
コンバートされた形状の内容
fbxの場合は、階層構造もUSDに渡ります。
Mesh自身は位置/回転/スケールのTransformを持っておらず、
Meshの親としてXformを割り当ててそこにTransformを持たせているようでした。
マテリアル
マテリアルはLooks内に格納されていました。
fbxからusdにコンバートしてインポートした場合は、すべてOmniPBRで指定されています。
テクスチャは、このOmniPBRのAlbedo Map/Roughness Map/Metallic Map/Ambient Occlusion Map/Normal Mapなどにドラッグして持っていきました。
Color Spaceの指定
テクスチャを割り当てた場合、各Color Spaceの指定はかなり重要です。
fbxからusdにコンバートした場合はすべてautoになっているため、ここは個々にチェックしていきます。
AlbedoのColor Spaceは、autoのままでOKです。sRGBが割り当てられています。
ReflectivityのRoughness/MetallicののColor Spaceは、autoのままでOKです。
sRGBが割り当てられています。
Ambient OcclusionのColor Spaceは、autoのままでOKです。sRGBが割り当てられています。
ただし、AOについてはOmniverseでのRTX Path-Tracedではあまり意味がない/必要がないかもしれません。
(パストレーシングで間接照明も正しく回り込んでいるため)
AOは、わずかなエフェクト的な利用になりそうな気がしています。
Normal MapのColor Spaceは、rawを指定します。
Normal Mapだけ、autoではない点に注意してください。
Normal Mapの凸凹の向きについて
Normal Mapの凸凹が逆転している場合は、「Normal Map Flip V Tangent」チェックボックスのOn/Offを切り替えます。
マテリアルでUSD標準のUsdPreviewSurfaceを使ってもよいか
Omniverse上では、UsdPreviewSurfaceは使わないほうがいいと思われます。
USDの標準では、マテリアルはUsdPreviewSurfaceが割り当てられます。
OmniPBRやOmniSurfaceはNVIDIA社のMDLを使った拡張になります。
そのため、おそらく現状はOmniPBRやOmniSurfaceはOmniverse以外では使えません。
他のDCCツールでUSDエクスポート対応していても、
マテリアルではUsdPreviewSurfaceのみを使っていると思います(Omniverse対応をうたっていない限り)。
しかし、UsdPreviewSurfaceの場合は以下の問題があります。
- 透過の場合の屈折表現ができない (Transmission/Glass系のパラメータを持たないため)
- Normal Mapでrawが指定できないため、凸凹が正しく表現できていない。そのため、境界部が見えたりする。
内部的な構造はもっと複雑な問題(UVを使ったタイリング指定など)があります。
これらよりOmniverse上のマテリアルでは基本的にはOmniPBRを使う、
ガラスのような透過と屈折が入る場合はOmniGlassを使う、としたほうがいいと思われます。
Omniverse Create 2021.3以降は、OmniSurfaceを使うと
非透過の場合とガラスのような透過、Transmissionでの透過時の減衰、SSSなど、
より高い表現が1つのShaderで指定できるようになります。
取り急ぎになりますが、現在のOmniverse Create 2021.3.3で
usdでないfbxなどで形状をインポートする場合の覚書でした。
バージョンアップすると仕様が変わるかもしれないため、あくまで参考としてご参照くださいませ。