[Omniverse] Curve(BasisCurves)の使用

  • by

Omniverse Create 2022.1.0で追加されたCurve機能を確認しました。
USDのフォーマットでCurveの機能は標準で用意されています。

https://graphics.pixar.com/usd/release/api/class_usd_geom_curves.html

Curveは曲線のラインを表現し、太さを与えてレンダリングに反映することができます。
これがOmniverse Create 2022.1.0/Omniverse Code 2022.1.0で表現できるようになりました。
今回はOmniverse Create 2022.1.1で確認しています。

USDでのCurveの記載

曲線は「BasisCurves」を使用します。
ベジェとして曲線のポイントを指定します。
usdaファイルでは以下のように記述します。

    def BasisCurves "Curve1"
    {
        uniform token basis = "bezier"
        int[] curveVertexCounts = [10]
        point3f[] points = [(-44.27, 0.0, 421.0), (-73.98, 0.0, 337.57),
           (-137.75, 0, 138.70), (-29.40, 0, 135.71), (78.94, 0, 132.72),
           (139.19, 0.0, 121.58), (151.17, 0.0, 62.65), (163.16, 0, 3.71),
           (165.55, 0, -53.46), (110.90, 0, -116.79)]
        uniform token type = "cubic"
        float[] widths = [10.0] (interpolation = "constant")

        double3 xformOp:rotateXYZ = (0, 0, 0)
        double3 xformOp:scale = (1, 1, 1)
        double3 xformOp:translate = (0, 0, 0)
        uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
    }

ビューの表示は以下のようになりました。

USDでは「BasisCurves」のPrimを配置しています。
「uniform token basis = "bezier"」で"bezier"(ベジェ)としてポイントを指定しています。
「int[] curveVertexCounts = [10]」は頂点数です。この場合は10個分。
「points」にポイントの情報を配列として入れます。
以下の並びになっています。

始点と終点は2つのポイントで指定、その間は3つのポイントを指定しています。
ベジェでの最小の指定は4ポイント(始点と終点、それぞれ2ポイント分)で構成されることになります。

「uniform token type = "cubic"」で曲線となります。
「uniform token type = "linear"」にしたときは折れ線になります。
「float[] widths」はチューブ状にしたときの太さの直径を指定します。
「[10.0] (interpolation = "constant")」と指定すると、同一の太さになります。

太さをポイントごとに変化させる

10個のポイントがある場合に、「float[] widths」で配列に10個の太さを指定します。

int[] curveVertexCounts = [10]
point3f[] points = [(-44.27, 0.0, 421.0), (-73.98, 0.0, 337.57),
   (-137.75, 0, 138.70), (-29.40, 0, 135.71), (78.94, 0, 132.72),
   (139.19, 0.0, 121.58), (151.17, 0.0, 62.65), (163.16, 0, 3.71),
   (165.55, 0, -53.46), (110.90, 0, -116.79)]
float[] widths = [0.0, 5.0, 10.0, 10.0, 10.0, 20.0, 25.0, 30.0, 30.0, 35.0] (interpolation = "vertex")

以下のようになりました。

「(interpolation = "vertex")」は省略でき、省略時はpointsと同じ個数の情報を指定します。

ハンドルを除いたベジェのポイント数(上記の場合は4つ)の太さを指定する場合、widthsでは「(interpolation = "varying")」を指定します。

int[] curveVertexCounts = [10]
point3f[] points = [(-44.27, 0.0, 421.0), (-73.98, 0.0, 337.57),
   (-137.75, 0, 138.70), (-29.40, 0, 135.71), (78.94, 0, 132.72),
   (139.19, 0.0, 121.58), (151.17, 0.0, 62.65), (163.16, 0, 3.71),
   (165.55, 0, -53.46), (110.90, 0, -116.79)]
float[] widths = [0.0, 20.0, 30.0, 0.0] (interpolation = "varying")

複数の曲線を指定

複数の曲線を指定する場合、「int[] curveVertexCounts」の配列に個々のポイント数を指定。
「point3f[] points」「float[] widths」はそれぞれを連続して指定します。

    def BasisCurves "Curve2"
    {
        uniform token basis = "bezier"
        int[] curveVertexCounts = [4, 4, 4]
        point3f[] points = [(0.0, 0.0, 0.0), (-10.0, 100.0, 0.0), (10.0, 110.0, 0.0), (0.0, 150.0, 0.0),
            (0.0, 0.0, 50.0), (-10.0, 100.0, 50.0), (10.0, 110.0, 50.0), (0.0, 150.0, 50.0),
            (0.0, 0.0, 100.0), (-10.0, 100.0, 100.0), (10.0, 110.0, 100.0), (0.0, 150.0, 100.0)
        ]
        uniform token type = "cubic"
        float[] widths = [20.0, 0.0, 25.0, 0.0, 30.0, 0.0] (interpolation = "varying")

        double3 xformOp:rotateXYZ = (0, 0, 0)
        double3 xformOp:scale = (1, 1, 1)
        double3 xformOp:translate = (0, 0, 0)
        uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
    }

この場合は3つの曲線が配置されました。

Omniverse Createでの曲線の配置

Omniverse Create 2022.1.1で曲線を配置します。
メインメニューの「Create」-「Basis Curves」-「From Bezier」を選択。
ビュー上で[Shift]キーを押しながらドラッグすると、ベジェのハンドルを伸ばします。
これを繰り返して曲線を作成。

[Enter]キーを押すと確定されます。

現状、操作をしているとグリッドが消えることがあります。
その場合は、Show/HideでGridをOff/Onしてトグルするとグリッドが再表示されます。

曲線を編集

StageウィンドウでBasisCurvesのPrimを選択し、右クリックのポップアップメニューから「Edit Control Vertices」を選択します。

これで編集モードに移行します。

[Shift]キーを押しながらクリックまたはドラッグすると、末尾に新たにポイントが追加されます。

ポイントをダブルクリックすると、マニピュレータを使ってポイントを移動できるようになります。

ハンドルも調整できます。

Enterキーで確定です。

Omniverse Createで曲線の太さを指定

Curveの配置直後は、Propertiesウィンドウを見ると「Visual」の「Purpose」が「guide」になっています。

この場合は実体がない曲線が表示されます。
このまま進めます。

「Raw USD Properties」を表示し内容を確認します。
「curveVertexCounts」が10となっており、「points」に10個分のポイントが指定されているのを確認できます。

「widths」はカラになってます。

ここに、クリップボードであらかじめ保持しているテキストをペーストする手段があります。
以下は10ポイント分の太さ指定です。(interpolation = "vertex")に相当します。
以下のテキストを選択し(前後の [ ] も忘れずに入れるようにしてください)、クリップボードに格納([Ctrl]+[C])します。

[0.0, 5.0, 10.0, 10.0, 10.0, 20.0, 25.0, 30.0, 30.0, 35.0]

「Raw USD Properties」で「widths」を探し、右クリックしてポップアップメニューを表示します。
「Paste」が選択できるようになっているため、これを選択します。

widthsの入力フィールド側でマウス右クリックしてポップアップメニューを出しても、
Pasteは選択できないようです。
widthsと表示されている箇所を右クリックするようにしてください。

「Purpose」を「default」に変更します。

以下のように曲線に太さが反映されました。

エラーが出る場合

「Purpose」を先に「default」に変更してwidthsを変更すると、以下のメッセージがConsoleに表示されます。

Not enough points for UsdGeomBasisCurves, 10 is required but 0 was found!

この場合は「Raw USD Properties」で「scene_visualization:drawWireframe」をOn/Offします。

これでBasicCurvesが更新されます。

ただ、Omniverse CreateのPropertiesのUIだけでwidthsを調整するのは難易度があるため、
一度usdaで保存してUSDとして追記するか、Pythonスクリプトから制御するほうがいいかもしれません。