Houdini 19.0 Pythonスクリプト

Pythonによるジオメトリノード(SOP)の定義

On this page

概要

  • Pythonを使って新しい、または再利用可能なジオメトリノードを定義したいのであれば、以下の“新しいノードタイプの作成”を参照してください。

  • 一回限りの変更をスクリプト化したいのであれば、Python SOPを使うことで、新しいノードタイプを作成することなく、ジオメトリ上のPython snippetを実行することができます。

新しいノードタイプの作成

  1. File ▸ New Asset を選択します。

  2. Operator Definition をpythonに、 Network Type を Geometry に設定します。

  3. Save To Library に、新しいノードタイプを保存するOTLライブラリファイルを設定します。

  4. Accept をクリックします。

    Edit Operator Type Propertiesウィンドウが表示されます。

  5. Edit Operator Type Propertiesウィンドウのオプションを使って新しいノードタイプのインターフェースを定義します。

  6. Code タブをクリックして、Pythonスクリプトを編集することでSOPの動作を定義します。

Tip

Type Propertiesウィンドウを閉じた後にスクリプトを編集したい場合、ノードのインスタンスをクリックして、 Type Properties を選択します。

コードの記述

ノードの入力のジオメトリを取得するには、以下のコードを記述します。

geo = hou.pwd().geometry()

hou.pwd()関数は、現在処理されているNodeを返し、geometry()はhou.Geometryオブジェクトを返します。Python SOPの1番目の入力にSOPが接続されていれば、Houdiniは、Pythonコードを実行する前にその入力のSOPのジオメトリをPython SOPのジオメトリにコピーします。

Tip

1番目以外の入力からジオメトリを取得するには、Nodeのinputs()メソッドを使用して、入力ノードを取得し、そのノードのgeometry()メソッドを使用することでジオメトリを取得することができます。

this_node = hou.pwd()
inputs = this_node.inputs()

# 2番目の入力からジオメトリを取得します
# (first input=0, second input=1, third=2など)
second_input_geo = inputs[1].geometry()

ジオメトリオブジェクト(この例ではgeo)に対してメソッドをコールすれば、出力するジオメトリを修正することができます。ジオメトリを制御する方法は、hou.Geometryオブジェクトのドキュメントを参照してください。

例えば、ポリゴンをジオメトリに追加するには、以下のコードを記述します:

poly = geo.createPolygon()
for position in (0,0,0), (1,0,0), (0,1,0):
    point = geo.createPoint()
    point.setPosition(position)
    poly.addVertex(point)

“filter”ノードよりも“source”ノードを作成したい場合は、単にType PropertiesでMaximum Inputsを0に設定すればいいだけです。hou.pwd().geometry()をコールすると追加可能な空っぽのジオメトリが返されます。

SOPを中断可能にする

指定した入力ジオメトリが膨大なために、ノードの処理に時間がかかる場合、 ⎋ Escを押してその処理を中断したい場合があります。SOPを中断可能にするには、定期的にhou.updateProgressAndCheckForInterrupt()をコールする必要があります。例えば、 ⎋ Escを押すと、このSOPの処理が停止します:

geo = hou.pwd().geometry()

# 各ポイントの移動量を調べるために、"t"パラメータを評価します。
translation = hou.Vector3(hou.parmTuple("t").eval())

for point in geo.points():
    # ポイント毎に新しい位置を設定します。
    point.setPosition(point.position() + translation)

    # ユーザがEscapeを押したかどうかを確認します。
    if hou.updateProgressAndCheckForInterrupt():
        break

SOPのエラーと警告

Python SOPに例外が発生すれば、ノードがエラーとして赤く表示されます。ノードをクリックすることで、そのエラーのスタックトレースを見ることができます。

ユーザ側にPythonスタックトレースを表示させないようにエラーメッセージを生成するには、hou.NodeErrorの例外を発生させてください。例えば、

raise hou.NodeError("Invalid parameter settings")

を実行すると、"Invalid parameter settings"のエラーメッセージでノードが赤く表示されます。同様に、ノードの警告を追加するには、hou.NodeWarningのインスタンスを発生させます。

新しいアトリビュート用ローカル変数の作成

hou.Geometry.addAttrib()には、Houdiniが、新しく追加したアトリビュート用のローカル変数を作成するかどうか設定するパラメータがあります。直接varmapアトリビュートを修正する必要はありません。

SOPコードのプロファイリング

PythonのcProfileモジュールによってPython SOPをプロファイリングすることができます。

Tip

UbuntuをOSに使用している場合、Ubuntuでは標準ライブラリがpstatsを持っていないので、aptitudeを使ってpython-profilerをインストールします。

トップレベルでたくさんのステートメントを記述するのではなく、関数内で作業が完結するように、あなたが作成したSOPにスクリプトを記述します。例:

def cook():
    poly = geo.createPolygon()
    for position in (0,0,0), (1,0,0), (0,1,0):
        point = geo.createPoint()
        point.setPosition(position)
        poly.addVertex(point)

cook()

cProfileをインポートし、あなたが作成した関数を直接コールせずにcProfile.runctxを使ってコールします:

def cook():
    poly = geo.createPolygon()
    for position in (0,0,0), (1,0,0), (0,1,0):
        point = geo.createPoint()
        point.setPosition(position)
        poly.addVertex(point)

cProfile.runctx('cook()', globals(), locals())

これにより、ノードが処理される時に、スクリプトのランタイムの要約がPythonシェルに表示されます。

SOPの一部をC++で記述する

SOPの一部をC++で記述する簡単な方法は、C++を使ったhouモジュールの拡張を参照してください。

デジタルアセット外でコードを保存する

バージョン管理システムでソースコードを管理するために、デジタルアセット外にソースコードを保存したい場合があります。Type Propertiesダイアログを使って、アセットのパラメータをセットアップし、Pythonソースコードをotlファイルに挿入することができます。

以下の関数を使えば、外部ファイルからPythonソースコードを読み取り、それをデジタルアセットに反映することができます:

def loadPythonSourceIntoAsset(otl_file_path, node_type_name, source_file_path):
    # Pythonソースコードを読み込みます。
    source_file = open(source_file_path, "rb")
    source = source_file.read()
    source_file.close()

    # OTLファイルからアセット定義を探します。
    definitions = [definition
        for definition in hou.hda.definitionsInFile(otl_file_path)
        if definition.nodeTypeName() == node_type_name]
    assert(len(definitions) == 1)
    definition = definitions[0]

    # アセットのPythonCookセクションにソースコードを保存します。
    definition.addSection("PythonCook", source)

Pythonスクリプト

はじめよう

次のステップ

リファレンス

  • hou

    Houdiniにアクセスできるサブモジュール、クラス、ファンクションを含んだモジュール。

導師レベル

Python Viewerステート

Pythonビューアハンドル

プラグインタイプ