HOME

Maneki Pipeline

ゲーム開発のためのプロシージャル

batで動作するミニマルなHoudiniパイプラインのgitリポジトリを公開しました

JenkinsなどのCIツールで動作させることを想定した「batを叩くと規定のパイプラインが動作する仕組み」を小規模なパイプラインで構成する

概要

Houdiniでbatを介して実行するためのミニマルな構成を作成したのでgithubで公開しました

ManekiPipeline/ minimal-houdini-batch
https://github.com/ManekiPipeline/minimal-houdini-batch?tab=readme-ov-file

良ければご利用ください。

Houdiniのバッチ動作について

houdiniでは内蔵しているPythonを利用してスクリプト経由でノードのクックなどを行うことができる。
以下のリファレンスページにコマンドラインからの実行方法としていくつかコードが紹介されている。

TOPネットワークをクック/実行する方法
https://www.sidefx.com/ja/docs/houdini/tops/cooking.html

どういった場合に使うかというと、バッチ形式にまとめておくとそれ単体でのパイプライン化されたツールはもちろん、JenkinsなどのCIツールのパイプラインに組み込みやすい。
プロジェクト運用上、パイプライン化しようとした場合結構用途は発生する。

CEDECのゼルダ講演の例
例えば想定できる用途として、ゼルダ講演で共有されていた毎晩のデータ取得などがある。
CEDECのゼルダ講演は非常にHoudiniの話題が多かったが、その中で地形情報の参照は毎晩Houdiniでボクセル情報を更新し続けていたという話だった。

ゲームメーカーズ| 『ゼルダの伝説 ティアーズ オブ ザ キングダム』のトーレルーフ開発秘話
https://gamemakers.jp/article/2024_09_02_77641/

規定の時間に自動で回そうとした場合、batなりでhythonに処理開始の命令を渡す流れをくむことで、JenkinsといったCIツールで定期的に回すことができる。のでゼルダでも似たような方法で運用していたのではないかなと思う。

ディレクトリとファイルの構成

主な構成要素は3つ。

  • 動作開始用のbatファイル
  • houdini内でシーンを開きTOPを実行するPythonスクリプト
  • 処理を行うTOPを含むhipシーン

batファイル
hythonのパスを指定してhoudini上で動作させるPythonを渡す。
(以下のパスは僕の環境のhoudiniインストールディレクトリです。gitに上がっているデータはhython.exeが指定されていないので利用する場合はパスを書き換えてください)

@echo off
"D:\\apps\\Side Effects Software\\Houdini 20.5.613\\bin\\hython.exe" "%~dp0\\scripts\\python\\exec_on_houdini.py"
pause

houdini内でシーンを開いてTOPを実行するPythonスクリプト
batからhythonにPythonファイルを渡すと起動と同時にそのpythonを実行してくれる。
今回はTOPを動作させる前提で作成している。
cookWorkItemsのblock引数を指定すると処理が終了するまでPythonが動作しない。
逆にblockが無い場合Pythonの処理が進むのでwhileなどで監視を行うような処理も作成できる。
(このスクリプトはcookWorkItemのあと処理が終了してしまうのでblockが無いとすべての処理が中断してしまう)

import hou

# hip読み込み
root_directory = hou.text.expandString("$HIP")  # シーンを開く前はパス変数$HIPでlaunch.batのパスを取得します
hip_name = "pipeline.hip"
hip_path = f"{root_directory}/hip/{hip_name}"
hou.hipFile.load(hip_path)
print(f"hipを読み込ました: {hip_path}")

# TOP実行
top_path = "/obj/topnet1"
top_node = hou.node(top_path)
to_cook = top_node.displayNode()
print(f"{top_node} のクックを開始しました")
to_cook.cookWorkItems(block=True)
print(u"すべてのワークが完了しました")

処理を行うhipファイル
サンプルのパイプライングラフ。
(外部の呼び出しに紐づいているのはhip名、TOP名のみなので、自分の処理に置き換える場合はそのあたりに注意してTOPの中身を置き換えてください)

filepatternで指定のパス以下のfbxを参照している

ROP Geometryの中でモデル読み込み、参照、json出力を行っている

ROP Geometryの中のpythonノードでdetailアトリビュートを出力している
import os
import hou
import pdg
import json
import pathlib

node = hou.pwd()
geo = node.geometry()

# ワークアイテムを参照
item = pdg.workItem()

# topアトリビュートを取得し、出力パスを作成
source = item.attribValue("filename")
hip_root = hou.expandString("$HIP")
# project_rootのパス取得が判りにくい書き方になっているので実運用ではpackage等でパス変数を作ることをお勧めします
# シンプルな構造として用意するうえではわかりずらくなってしまうので今回packageは割愛しました
project_root = os.path.dirname(hip_root)
output_directory = pathlib.Path(f"{project_root}/output")
output_directory.mkdir(parents=True, exist_ok=True)
output_file = f"{output_directory}/{source}.json".replace(os.sep, "/")

# jsonに含めるアトリビュートを参照
extract_data = {}
for _detail_attr in geo.globalAttribs():
    attr_name = _detail_attr.name()
    detail_value = geo.attribValue(_detail_attr.name())
    extract_data[attr_name] = detail_value

# jsonとして出力
with open(output_file, "w") as f:
    json.dump(extract_data, f, indent=4)

実行結果

パスなどを設定し、launch.batを介してサンプルシーンを実行するとディレクトリ以下のfbxに含まれるポリゴン数をjsonとして出力する。

サンプルを実行すると指定ディレクトリ以下にあるfbxごとのポリゴン数をjsonとして出力する

PythonでDetailアトリビュートを出力しているのでROP Geometryを編集し、他のDetailアトリビュートを追加すればそれも出力される。


一度作ると便利な気がしたので作成しました。

fish_ball

プロシージャル魚類